Journal 2022-06-18
Rust
- pretty_assertions: Overwrite
assert_eq!
with a drop-in replacement, adding a colorful diff.
Custom Serde Serialize
It could be difficult to make a custom implementation of the serde::Serialize
trait. Like serializing a Vec
into a tree or graph structure. This is because
you need to consume the serde::Serializer
to create a data type like
structure or sequence. A trick I implemented to overcome this limitation is to
implement the visitor patten to a custom enum
that implements Serialize
itself.
You start by implementing the Serialize
for your structure:
use serde::Serialize;
impl<T> Serialize for Vec<T>
where
T: Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut seq = serializer.serialize_seq(Some(self.len()))?;
for e in self {
...
}
seq.end()
}
}
And when you need an additional structure you create an enum and implement
Serialize
for it:
enum ElementSerialize<T> {
Node{ elements: &[T], ...},
Childs{ elements: &[T], ...}
}
...
impl<T> Serialize for ElementSerialize<T>
where
T: Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match self {
Node{...} => todo!(), // Can now consume the serializer inside the match
Childs{...} => todo!(),
}
}
}
And you can wrap the value in the Serialize of the structure:
...
// Inside impl Serialize for Vec
for e in self {
seq.serialize_element(ElementSerialize::Node(...))?;
}
...
Publish a package
To publish a packages to crates.io:
- Register on the site
- Create a new API Token and save it
- Set the token to work with cargo:
- Run
cargo login
to set the token in the$CARGO_HOME/credentials.toml
file - Otherwise for CI/CD set the
CARGO_REGISTRY_TOKEN
environment variable
- Run
- Run
cargo publish
Publish with GitHub Actions
A simple workflow to publish a create when on a new release is the following:
name: Publish
on:
release:
types: [published]
workflow_dispatch:
env:
CARGO_TERM_COLOR: always
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/cache@v3
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Check
run: cargo check --all-targets --all-features --verbose --locked
- name: Build
run: cargo build --verbose --locked
- name: Run tests
run: cargo test --all-targets --all-features --verbose --locked
- name: Publish crate
run: cargo publish --verbose --locked
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
<!-- Morning -->
<!-- What do I want to do today? -->
<!-- Evening -->
<!-- What did I learn today? -->
<!-- Things I learned -->
<!-- Useful tools and libraries -->