sark-gen 0.2.0

Sark proc-macro generators
Documentation
use proc_macro2::TokenStream;
use quote::quote;
use syn::{Result, Type};

use super::scalar::{Classified, Scalar};

pub(super) struct Encode;

impl Encode {
    pub(super) fn len_expr(ty: &Type, raw: bool, access: TokenStream) -> Result<TokenStream> {
        let class = Classified::of(ty)?;
        let len = match class.scalar {
            Scalar::U64 => quote!(sark::json::Encode::u64_len(#access)),
            Scalar::Bool => quote!(if #access { 4usize } else { 5usize }),
            Scalar::LocalFrameBytes | Scalar::InlineToken => {
                if raw {
                    quote!(#access.len())
                } else {
                    quote!(sark::json::Encode::str_len(#access.as_bytes()))
                }
            }
        };
        Ok(if class.optional {
            quote! {
                match #access {
                    Some(value) => #len,
                    None => 4usize,
                }
            }
        } else {
            len
        })
    }

    pub(super) fn write_expr(
        ty: &Type,
        raw: bool,
        plain: bool,
        access: TokenStream,
    ) -> Result<TokenStream> {
        let class = Classified::of(ty)?;
        let write = match class.scalar {
            Scalar::U64 => quote!(sark::json::Encode::extend_u64(__out, #access);),
            Scalar::Bool => quote! {
                if #access {
                    __out.extend_from_slice(b"true");
                } else {
                    __out.extend_from_slice(b"false");
                }
            },
            Scalar::LocalFrameBytes | Scalar::InlineToken => {
                if raw {
                    quote!(__out.extend_from_slice(#access.as_bytes());)
                } else if plain {
                    quote! {
                        __out.extend_from_slice(b"\"");
                        __out.extend_from_slice(#access.as_bytes());
                        __out.extend_from_slice(b"\"");
                    }
                } else {
                    quote!(sark::json::Encode::extend_str(#access.as_bytes(), __out);)
                }
            }
        };
        Ok(if class.optional {
            quote! {
                match #access {
                    Some(value) => { #write }
                    None => { __out.extend_from_slice(b"null"); }
                }
            }
        } else {
            write
        })
    }
}