typed-ident: v0.0.4 Release

Today marks the official release of the v0.0.4 version of typed-ident!

This update adds support for serde serialization and deserialization via an optional feature.

You can add the dependency by editing your Cargo.toml:

[dependencies]
typed-ident = "0.0.4"

Or by using cargo add:

cargo add typed-ident

Or update by using cargo update:

cargo update -p typed-ident

You can now enable the optional serde feature to allow for support for serialization and deserialization.

The identifier parts serialize and deserialize as string-like values:

  • &Chunk<...> (borrowed)
  • &Fragment<...> (borrowed)
  • &Ident<...> (borrowed)
  • Box<Chunk<...>> (owned)
  • Box<Fragment<...>> (owned)
  • Box<Ident<...>> (owned)
  • Cow<Chunk<...>> (either)
  • Cow<Fragment<...>> (either)
  • Cow<Ident<...>> (either)
  • FragmentBuf<...> (owned)

The delimiter types serialize and deserialize as a single character:

  • AsciiFlatLine
  • AsciiPunctuation
  • HyphenMinus
  • LowLine

In most cases, you’ll probably want to take ownership of the deserialized value instead of it being tied to the serialized data. To accomplish that, you’ll use the Box<Ident<...>> type:

#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub struct OwnedExample {
    ident: Box<UpperCamelIdent>,
}

#[test]
fn owned_example() -> Result<(), Box<dyn std::error::Error>> {
    let example = OwnedExample {
        ident: UpperCamelIdent::new_boxed("UpperCamelIdent")?,
    };

    // You can serialize to some serde format...
    let serialized = serde_json::to_string(&example)?;
    assert_eq!(serialized, r#"{"ident":"UpperCamelIdent"}"#);
    let deserialized = serde_json::from_str(&serialized)?;
    assert_eq!(example, deserialized);

    Ok(())
}

If you truly do want to borrow from the serialized data, you can use the reference type like so:

#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub struct BorrowedExample<'a> {
    #[serde(borrow)]
    ident: &'a UpperCamelIdent,
}

#[test]
fn borrowed_example() -> Result<(), Box<dyn std::error::Error>> {
    let example = BorrowedExample {
        ident: UpperCamelIdent::new("UpperCamelIdent")?,
    };

    // You can serialize to some serde format...
    let serialized = serde_json::to_string(&example)?;
    assert_eq!(serialized, r#"{"ident":"UpperCamelIdent"}"#);
    let deserialized = serde_json::from_str(&serialized)?;
    assert_eq!(example, deserialized);

    Ok(())
}

If you want either of the two, you can use Cow as expected (which by default creates an Owned value):

#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub struct CowExample<'a> {
    ident: Cow<'a, UpperCamelIdent>,
}

#[test]
fn cow_example() -> Result<(), Box<dyn std::error::Error>> {
    let example = CowExample {
        ident: Cow::Borrowed(UpperCamelIdent::new("UpperCamelIdent")?),
    };

    // You can serialize to some serde format...
    let serialized = serde_json::to_string(&example)?;
    assert_eq!(serialized, r#"{"ident":"UpperCamelIdent"}"#);
    let deserialized = serde_json::from_str(&serialized)?;
    assert_eq!(example, deserialized);
    std::assert_matches!(deserialized.ident, Cow::Owned(_));

    Ok(())
}

While adding this feature, it became obvious that Error and SyntaxError didn’t implement the Error trait as one would expect. So there’s also a small patch to fix that (as you can see from the above sample code).

You can view the complete list of important changes in the changelog.

Thanks for reading, and I hope these improvements are useful for you!

← Previous Announcement
typed-ident: v0.0.3 Release