fn deserialize(bytes: &mut &[u8]) -> Result<Self, DeserializeError> {
        let tag_count = leb128::read::unsigned(bytes).map_err(DeserializeErrorKind::Leb128)?;
        let mut architecture = None;
        let mut hasher = None;
        let mut depth = None;
        let mut is_recovering = false;
        let mut custom = HashMap::new();

        for _ in 0..tag_count {
            let key = Self::deserialize_str(bytes)?;
            let value = Self::deserialize_str(bytes)?;
            match key {
                "architecture" => architecture = Some(value.to_owned()),
                "hasher" => hasher = Some(value.to_owned()),
                "depth" => {
                    let parsed = value.parse::<usize>().map_err(|err| {
                        DeserializeErrorKind::MalformedTag {
                            name: "depth",
                            err: err.into(),
                        }
                    })?;
                    depth = Some(parsed);
                }
                "is_recovering" => {
                    let parsed = value.parse::<bool>().map_err(|err| {
                        DeserializeErrorKind::MalformedTag {
                            name: "is_recovering",
                            err: err.into(),
                        }
                    })?;
                    is_recovering = parsed;
                }
                key => {
                    if let Some(custom_key) = key.strip_prefix("custom.") {
                        custom.insert(custom_key.to_owned(), value.to_owned());
                    } else {
                        return Err(DeserializeErrorKind::UnknownTag(key.to_owned()).into());
                    }
                }
            }
        }
        Ok(Self {
            architecture: architecture.ok_or(DeserializeErrorKind::MissingTag("architecture"))?,
            hasher: hasher.ok_or(DeserializeErrorKind::MissingTag("hasher"))?,
            depth: depth.ok_or(DeserializeErrorKind::MissingTag("depth"))?,
            is_recovering,
            custom,
        })
    }
Tags are serialized as a length-prefixed list of `(&str, &str)` tuples, where each
`&str` is length-prefixed as well. All lengths are encoded using LEB128.
Custom tag keys are prefixed with `custom.` to ensure they don't intersect with standard tags.
core/lib/merkle_tree/src/storage/serialization.rs