// run-pass #![allow(unused_must_use)] #![allow(dead_code)] #![allow(unused_imports)] use std::fmt; use std::io::prelude::*; use std::io::Cursor; use std::slice; use std::marker::PhantomData; trait Encoder { type Error; } trait Encodable { fn encode(&self, s: &mut S) -> Result<(), S::Error>; } struct JsonEncoder<'a>(PhantomData<&'a mut ()>); impl Encoder for JsonEncoder<'_> { type Error = (); } struct AsJson<'a, T> { inner: &'a T, } impl<'a, T: for<'r> Encodable>> fmt::Display for AsJson<'a, T> { /// Encodes a json value into a string fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { Ok(()) } } fn as_json(t: &T) -> AsJson<'_, T> { AsJson { inner: t } } struct OpaqueEncoder(Vec); impl Encoder for OpaqueEncoder { type Error = (); } struct Foo { baz: bool, } impl Encodable for Foo { fn encode(&self, _s: &mut S) -> Result<(), S::Error> { Ok(()) } } struct Bar { froboz: usize, } impl Encodable for Bar { fn encode(&self, _s: &mut S) -> Result<(), S::Error> { Ok(()) } } enum WireProtocol { JSON, Opaque, // ... } fn encode_json Encodable>>(val: &T, wr: &mut Cursor>) { write!(wr, "{}", as_json(val)); } fn encode_opaque>(val: &T, wr: Vec) { let mut encoder = OpaqueEncoder(wr); val.encode(&mut encoder); } pub fn main() { let target = Foo { baz: false }; let proto = WireProtocol::JSON; match proto { WireProtocol::JSON => encode_json(&target, &mut Cursor::new(Vec::new())), WireProtocol::Opaque => encode_opaque(&target, Vec::new()), } }