Generics with particular type "instantiation" prevention

⚓ Rust    📅 2025-08-13    👤 surdeus    👁️ 4      

surdeus

Now I'm trying to write a (yet another) YAML parser.
YAML has several context for several items.

  • Context are always given at compile-time, not a runtime parameter
  • Some parser defines all context variants while other defines only subset of context.
    For example, YAML Ain’t Markup Language (YAML™) revision 1.2.2 nb-double-text is defined for 4 contexts out of 6.

I want to make this context non-runtime parameter but have no idea what's a good approach. I considered a few approaches but all seem not good enough.

  1. Make it enum and use const generics + specialization. I gave it up because
    • it's impossible to have enum as const generics parameter
    • it's impossible to specialize generics
  2. Make all Context marker structs, implement a trait Context.
    • I cannot find a way to define a way to omit certain context definition on parser.
  3. Make all context as a function suffix, use macro to make it a bit better.
    • That is promising while the cost of implementation is a bit high without procedure macro which is a bit too much of hassle.

Can anyone suggest me a good approach? Thanks in advance


1 implementation example

enum YamlContext {FlowIn, FlowOut, ...}

fn parse_nb_double_text<const ctx: YamlContext>(input: &mut &str) -> Result<&str>;
// how can I define this for only FlowIn/FlowOut/BlockKey/FlowKey??

2 implementation example

trait YamlContext: DoubleTextParse {}

struct FlowIn {}

impl YamlContext for FlowIn {}

fn parse_nb_double_text<Ctx: YamlContext>(input: &mut &str) -> Result<&str> {
  <Ctx as DoubleTextParse>::parse(input)
}

trait DoubleTextParse {
  fn parse(...);
}

// FIXME: I need to impl DoubleTextParse for all context, while I don't need it for BlockIn/BlockOut.

3 example

// define all _$context variants.
fn parse_nb_double_text_flow_in(...)
fn parse_nb_double_text_flow_out(...)
fn parse_nb_double_text_flow_key(...)
fn parse_nb_double_text_block_key(...)

// problem is that forwarding context is cumbersome and error-prone.

1 post - 1 participant

Read full topic

🏷️ Rust_feed