asn1rs-model 0.2.2

Rust, Protobuf and SQL model definitions for asn1rs
Documentation
use crate::model::Size;
use syn::parse::{Parse, ParseStream};
use syn::Ident;
use syn::Lit;
use syn::Token;

impl Parse for Size {
    fn parse<'a>(input: ParseStream) -> syn::Result<Self> {
        let min = value(input)?.ok_or_else(|| input.error("invalid min"))?;
        if input.is_empty() {
            Ok(Size::Fix(min, false))
        } else if input.peek(Token![,]) {
            let _ = input.parse::<Token![,]>()?;
            let _ = input.parse::<Token![.]>()?;
            let _ = input.parse::<Token![.]>()?;
            let _ = input.parse::<Token![.]>()?;
            Ok(Size::Fix(min, true))
        } else {
            let _ = input.parse::<Token![.]>()?;
            let _ = input.parse::<Token![.]>()?;
            let max = value(input)?.ok_or_else(|| input.error("invalid max"))?;
            let extensible = if input.peek(Token![,]) && input.peek2(Token![.]) {
                let _ = input.parse::<Token![,]>()?;
                let _ = input.parse::<Token![.]>()?;
                let _ = input.parse::<Token![.]>()?;
                let _ = input.parse::<Token![.]>()?;
                true
            } else {
                false
            };

            if min == max {
                Ok(Size::Fix(min, extensible))
            } else {
                Ok(Size::Range(min, max, extensible))
            }
        }
    }
}

fn value(input: ParseStream) -> syn::Result<Option<usize>> {
    if let Ok(Lit::Int(int)) = input.parse::<Lit>() {
        Ok(Some(int.base10_digits().parse::<usize>().map_err(
            |_| input.error("Expected non-negative int literal"),
        )?))
    } else if let Ok(ident) = input.parse::<Ident>() {
        let lc = ident.to_string().to_lowercase();
        if lc == "min" || lc == "max" {
            Ok(None)
        } else {
            Err(input.error(format!(
                "Invalid identifier, accepted identifiers are: min, max but got: {}",
                lc
            )))
        }
    } else {
        Err(input.error("Cannot parse token"))
    }
}