///|
/// Parse a DICOM Part 10 byte sequence into its data set.
pub fn parse(bytes : Bytes) -> DataSet raise ParseError {
  if bytes.length() < 132 {
    raise ParseError::Truncated(offset=0, needed=132, remaining=bytes.length())
  }
  let reader = byte_reader(bytes)
  reader.skip(128)
  let magic = reader.read_bytes(4)
  if magic != b"DICM" {
    raise ParseError::InvalidMagic(offset=128)
  }
  let meta = parse_elements(reader, true, Some(0x0002))
  let transfer_syntax = match meta.get(transfer_syntax_uid()) {
    Some({ value: Text(value), .. }) => value
    _ => "1.2.840.10008.1.2.1"
  }
  let explicit = transfer_syntax != "1.2.840.10008.1.2"
  let dataset = parse_elements(reader, explicit, None)
  let result = data_set()
  for element in meta.elements() {
    result.set(element)
  }
  for element in dataset.elements() {
    result.set(element)
  }
  result
}

///|
fn parse_elements(
  reader : ByteReader,
  explicit : Bool,
  stop_group : Int?,
) -> DataSet raise ParseError {
  let result = data_set()
  while reader.remaining() > 0 {
    if reader.remaining() < 4 {
      raise ParseError::Truncated(
        offset=reader.position(),
        needed=4,
        remaining=reader.remaining(),
      )
    }
    let group = reader.peek_u16()
    if stop_group is Some(expected) && group != expected {
      break
    }
    let actual_group = reader.read_u16()
    let element = reader.read_u16()
    let tag = tag(actual_group, element)
    let vr = if explicit {
      let code = reader.read_ascii(2)
      value_representation(code, offset=reader.position() - 2)
    } else {
      value_representation(dictionary_vr(tag), offset=reader.position()) catch {
        _ => UN
      }
    }
    let length = if explicit {
      if vr.uses_long_header() {
        reader.skip(2)
        reader.read_u32()
      } else {
        reader.read_u16()
      }
    } else {
      reader.read_u32()
    }
    if length == 0xffffffff {
      raise ParseError::Unsupported(
        offset=reader.position() - 4,
        message="undefined-length elements are not supported yet",
      )
    }
    let value_bytes = reader.read_bytes(length)
    result.set(data_element(tag, vr, decode_value(vr, value_bytes)))
  }
  result
}