protify 0.1.4

A Rust-first protobuf framework to generate packages from rust code, with validation included
Documentation
# Proxies As A Translation Layer

Messages and oneofs can be proxied. Doing so will generate a new struct/enum with the same name, followed by a `Proto` suffix (i.e. MyMsg -> MyMsgProto).

Proxied messages/oneofs unlock the following features:

- A field/variant can be missing from the proto struct, but present in the proxy (akin to the `skip` attribute with `serde`)
- Enums can be represented with their actual rust enum type, rather than being pure integers
- Oneofs don't need to be wrapped in `Option`
- Messages don't need to be wrapped in `Option`
- We can use types that are not supported by prost and map them with custom conversions

By default, the macro will generate a conversion from proxy to proto and vice versa that just calls `.into()` for each field/variant. So if the field's prost type implements `From` with the proxy field and vice versa, no additional attributes are required.

To provide custom conversions, you can use the `from_proto` and `into_proto` attributes on the container (to replace the automatically generated impl as a whole) or on individual fields/variants.

The proxied structs/enums will also implement [`ProxiedMessage`](crate::ProxiedMessage) or [`ProxiedOneof`](crate::ProxiedOneof), whereas the proxies will implement [`MessageProxy`](crate::MessageProxy) and [`OneofProxy`](crate::OneofProxy).

```rust
use protify::*;
use std::sync::Arc;

proto_package!(MY_PKG, name = "my_pkg");
define_proto_file!(MY_FILE, name = "my_file.proto", package = MY_PKG);

// Generates a MsgProto struct that is prost-compatible
#[proto_message(proxied)]
pub struct Msg {
	// Requires setting the type manually as the type
	// is not prost-compatible
	#[proto(string)]
	// Must provide a custom `into_proto` impl because `Arc<str>` does not support `Into<String>`
	#[proto(into_proto = |v| v.as_ref().to_string())]
	pub name: Arc<str>,
	// Ignored field. Conversion from proto will use `Default::default()` unless a custom
	// conversion is specified
	#[proto(ignore)]
	pub rust_only: i32,
	// In proxied messages, we can use `default` for oneofs
	// so that using `Option` is not required.
	// The default conversion will call `ProxiedOneofProto::default().into()`
	// if the field is `None` in the proto struct.
	#[proto(oneof(proxied, default, tags(1, 2)))]
	pub oneof: ProxiedOneof,
	// We can do the same for messages too
	#[proto(message(default))]
	pub message_with_default: Msg2,
	// We can use the enum directly as the type
	#[proto(enum_)]
	pub enum_: TestEnum,
}

#[proto_enum]
pub enum TestEnum {
	Unspecified,
	A,
	B,
}

// Direct implementation. The prost attributes will be directly
// injected in it
#[proto_message]
pub struct Msg2 {
	pub id: i32,
	// In direct impls, enums are just integers
	#[proto(enum_(TestEnum))]
	pub enum_: i32,
}

// Generates the `ProxiedOneofProto` enum
#[proto_oneof(proxied)]
pub enum ProxiedOneof {
	#[proto(string, tag = 1, into_proto = |v| v.as_ref().to_string())]
	A(Arc<str>),
	#[proto(tag = 2)]
	B(u32),
}

impl Default for ProxiedOneofProto {
	fn default() -> Self {
		Self::B(1)
	}
}

fn main() {
	let msg = MsgProto::default();
	// Using the `ProxiedMessage` trait
	let proxy = msg.into_proxy();
	// Using the `MessageProxy` trait
	let msg_again = proxy.into_message();
}
```