Skip to content

Commit

Permalink
WIP (#16)
Browse files Browse the repository at this point in the history
  • Loading branch information
loganmzz committed Jul 24, 2024
1 parent 699fcc5 commit 9c09c5b
Show file tree
Hide file tree
Showing 10 changed files with 957 additions and 43 deletions.
35 changes: 35 additions & 0 deletions macon-config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,41 @@
}
}
}
},
"extend_types": {
"description": "Override pathes that should implement Extend",
"type": "object",
"properties": {
"includes": {
"description": "Pathes that should implement Extend",
"type": "array",
"items": {
"oneOf": [
{
"description": "Path that should implement Extend",
"type": "string"
},
{
"description": "Path and associated wrapped type",
"type": "object",
"properties": {
"path": {
"description": "Path that should implement Extend",
"type": "string"
},
"wrapped": {
"description": "Contained type",
"type": "string"
},
"required": [
"path"
]
}
}
]
}
}
}
}
}
}
55 changes: 54 additions & 1 deletion macon_api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
//! See it for all details.
//!
use std::fmt::Debug;
use std::{
fmt::Debug, ops::Deref, vec
};

/// Builder field type when building struct implementing [`Default`].
#[derive(Default,)]
Expand All @@ -25,6 +27,14 @@ pub enum Defaulting<T: Default> {
Set(T),
}

/// Builder field type when target implment [`Extend`].
pub struct Extending<C,I> {
/// Collecting items
items: Vec<I>,
/// Building value
value: C,
}

/// Builder field type for `Panic` or `Result` mode.
#[derive(Default,)]
pub enum Building<T> {
Expand Down Expand Up @@ -82,6 +92,49 @@ impl<T: Default> Defaulting<T> {
}
}

impl<C, I> Default for Extending<C, I> where C: Default {
fn default() -> Self {
Self {
items: Default::default(),
value: Default::default(),
}
}
}

impl<C, I> Deref for Extending<C, I> {
type Target = C;

fn deref(&self) -> &Self::Target {
&self.value
}
}

impl<C, I> Extend<I> for Extending<C, I> {
/// Store `iter` values into `items` (until container is created)
fn extend<T: IntoIterator<Item = I>>(&mut self, iter: T) {
self.items.extend(iter)
}
}

impl<C, I> IntoIterator for Extending<C, I> {
type Item = I;
type IntoIter = vec::IntoIter<I>;
fn into_iter(self) -> Self::IntoIter {
self.items.into_iter()
}
}

impl<C, I> Extending<C, I> {
pub fn value_mut(&mut self) -> &mut C {
&mut self.value
}

/// Consume to return `value` and collected `items`.
pub fn unwrap(self) -> (C, Vec<I>) {
(self.value, self.items)
}
}

impl<T> Debug for Building<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Expand Down
60 changes: 60 additions & 0 deletions macon_derive/src/common.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
use std::{
fmt::{
Debug,
Display,
},
ops::Deref,
};
use quote::ToTokens;
use syn::Type;

pub struct TokenDisplay<T: ToTokens>(T);

pub type MType = TokenDisplay<Type>;

impl<T: ToTokens> Debug for TokenDisplay<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!("{}", self))
}
}

impl<T: ToTokens> Display for TokenDisplay<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!("{}", self.0.to_token_stream()))
}
}

impl<T: ToTokens> From<T> for TokenDisplay<T> {
fn from(value: T) -> Self {
Self(value)
}
}

impl<T: ToTokens> Deref for TokenDisplay<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}

impl<T: ToTokens> ToTokens for TokenDisplay<T> {
fn to_token_stream(&self) -> proc_macro2::TokenStream {
self.0.to_token_stream()
}

fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
self.0.to_tokens(tokens)
}

fn into_token_stream(self) -> proc_macro2::TokenStream
where
Self: Sized, {
self.0.into_token_stream()
}
}

impl<T: ToTokens + PartialEq> PartialEq<T> for TokenDisplay<T> {
fn eq(&self, other: &T) -> bool {
self.0.eq(other)
}
}
93 changes: 76 additions & 17 deletions macon_derive/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ pub fn get() -> &'static anyhow::Result<Configuration> {
#[derive(Debug,)]
pub struct Configuration {
default_types: TypeSet,
option_types: TypeSet<OptionTypeSetItem>,
option_types: TypeSet<ContainerTypeSetItem>,
extend_types: TypeSet<ContainerTypeSetItem>,
}

pub trait TypeSetItem {
Expand Down Expand Up @@ -109,6 +110,7 @@ impl<V: TypeSetItem> TypeSet<V> {
.map(|segment| segment.ident.to_string())
.collect::<Vec<_>>()
.join("::");

self.match_str(&str)
}

Expand All @@ -133,7 +135,12 @@ impl Default for Configuration {
fn default() -> Self {
let default_types = Configuration::default_default_types();
let option_types = Configuration::default_option_types();
Self { default_types, option_types, }
let extend_types = Configuration::default_extend_types();
Self {
default_types,
option_types,
extend_types,
}
}
}

Expand All @@ -157,10 +164,15 @@ impl Configuration {
crate_config.option_types.map_includes(|i| i.into()),
Self::default_option_types,
);
let extend_types = TypeSet::create(
crate_config.extend_types.map_includes(|i| i.into()),
Self::default_extend_types,
);

let this = Self {
default_types,
option_types,
extend_types,
};
#[cfg(feature = "debug")]
eprintln!("Merge configuration\n{:#?}", this);
Expand Down Expand Up @@ -197,18 +209,26 @@ impl Configuration {
.add_path("std::collections::hash_set::HashSet")
}

pub fn default_option_types() -> TypeSet<OptionTypeSetItem> {
pub fn default_option_types() -> TypeSet<ContainerTypeSetItem> {
TypeSet::default()
.add_path("std::option::Option")
.add_path("core::option::Option")
}

pub fn default_extend_types() -> TypeSet<ContainerTypeSetItem> {
TypeSet::default()
.add_path("std::vec::Vec")
}

pub fn default_types(&self) -> &TypeSet {
&self.default_types
}
pub fn option_types(&self) -> &TypeSet<OptionTypeSetItem> {
pub fn option_types(&self) -> &TypeSet<ContainerTypeSetItem> {
&self.option_types
}
pub fn extend_types(&self) -> &TypeSet<ContainerTypeSetItem> {
&self.extend_types
}
}

#[derive(Debug,Deserialize,)]
Expand All @@ -218,31 +238,33 @@ struct CrateConfiguration {
pub version: String,
#[serde(default)]
pub default_types: TypeSetConfiguration<String>,
#[serde(default = "default_typesetconfiguration", deserialize_with="deserialize_crateconfiguration_option_types")]
pub option_types: TypeSetConfiguration<OptionTypeSetItem>,
#[serde(default = "default_typesetconfiguration", deserialize_with="deserialize_crateconfiguration_container_types")]
pub option_types: TypeSetConfiguration<ContainerTypeSetItem>,
#[serde(default = "default_typesetconfiguration", deserialize_with="deserialize_crateconfiguration_container_types")]
pub extend_types: TypeSetConfiguration<ContainerTypeSetItem>,
}

fn deserialize_crateconfiguration_option_types<'de, D>(deserializer: D) -> std::result::Result<TypeSetConfiguration<OptionTypeSetItem>, D::Error>
fn deserialize_crateconfiguration_container_types<'de, D>(deserializer: D) -> std::result::Result<TypeSetConfiguration<ContainerTypeSetItem>, D::Error>
where
D: Deserializer<'de>,
{
let decoded: TypeSetConfiguration<OptionTypeSetItemConfiguration> = Deserialize::deserialize(deserializer)?;
Ok(decoded.map_includes(OptionTypeSetItem::from))
Ok(decoded.map_includes(ContainerTypeSetItem::from))
}

#[derive(Debug,Default,Deserialize,PartialEq,)]
pub struct OptionTypeSetItem {
pub struct ContainerTypeSetItem {
pub path: String,
pub wrapped: Option<String>,
}

impl TypeSetItem for OptionTypeSetItem {
impl TypeSetItem for ContainerTypeSetItem {
fn path(&self) -> String {
self.path.clone()
}
}

impl From<&str> for OptionTypeSetItem {
impl From<&str> for ContainerTypeSetItem {
fn from(path: &str) -> Self {
Self {
path: path.to_owned(),
Expand All @@ -255,7 +277,7 @@ impl From<&str> for OptionTypeSetItem {
#[serde(untagged)]
pub enum OptionTypeSetItemConfiguration {
String(String),
Item(OptionTypeSetItem),
Item(ContainerTypeSetItem),
}

impl Default for OptionTypeSetItemConfiguration {
Expand All @@ -264,7 +286,7 @@ impl Default for OptionTypeSetItemConfiguration {
}
}

impl From<OptionTypeSetItemConfiguration> for OptionTypeSetItem {
impl From<OptionTypeSetItemConfiguration> for ContainerTypeSetItem {
fn from(value: OptionTypeSetItemConfiguration) -> Self {
match value {
OptionTypeSetItemConfiguration::String(string) => string.as_str().into(),
Expand Down Expand Up @@ -402,7 +424,7 @@ mod tests {
let mut option_types_includes = option_types.includes.iter();
assert_eq!(
option_types_includes.next(),
Some(&OptionTypeSetItem {
Some(&ContainerTypeSetItem {
path: "AsString".to_owned(),
wrapped: None,
}),
Expand All @@ -411,25 +433,62 @@ mod tests {

assert_eq!(
option_types_includes.next(),
Some(&OptionTypeSetItem { path: "AsItemWithoutWrapped".to_owned(), wrapped: None, }),
Some(&ContainerTypeSetItem { path: "AsItemWithoutWrapped".to_owned(), wrapped: None, }),
"option_types.includes[1]\n{:#?}", config
);

assert_eq!(
option_types_includes.next(),
Some(&OptionTypeSetItem { path: "AsItemWithShortWrapped".to_owned(), wrapped: Some("ShortWrapped".to_string()), }),
Some(&ContainerTypeSetItem { path: "AsItemWithShortWrapped".to_owned(), wrapped: Some("ShortWrapped".to_string()), }),
"option_types.includes[2]\n{:#?}", config
);

assert_eq!(
option_types_includes.next(),
Some(&OptionTypeSetItem { path: "AsItemWithFullWrapped".to_owned(), wrapped: Some("::full::path::FullWrapped".to_string()), }),
Some(&ContainerTypeSetItem { path: "AsItemWithFullWrapped".to_owned(), wrapped: Some("::full::path::FullWrapped".to_string()), }),
"option_types.includes[3]\n{:#?}", config
);

assert!(option_types_includes.next().is_none(), "option_types.includes[4]\n{:#?}", config);

let mut option_types_excludes = option_types.excludes.iter();
assert_eq!(option_types_excludes.next(), None, "option_types.excludes[0]\n{:#?}", config);


let extend_types = &config.extend_types;
assert_eq!(extend_types.defaults, true, "extend_types.defaults");

let mut extend_types_includes = extend_types.includes.iter();
assert_eq!(
extend_types_includes.next(),
Some(&ContainerTypeSetItem {
path: "AsString".to_owned(),
wrapped: None,
}),
"extend_types.includes[0]\n{:#?}", config
);

assert_eq!(
extend_types_includes.next(),
Some(&ContainerTypeSetItem { path: "AsItemWithoutWrapped".to_owned(), wrapped: None, }),
"extend_types.includes[1]\n{:#?}", config
);

assert_eq!(
extend_types_includes.next(),
Some(&ContainerTypeSetItem { path: "AsItemWithShortWrapped".to_owned(), wrapped: Some("ShortWrapped".to_string()), }),
"extend_types.includes[2]\n{:#?}", config
);

assert_eq!(
extend_types_includes.next(),
Some(&ContainerTypeSetItem { path: "AsItemWithFullWrapped".to_owned(), wrapped: Some("::full::path::FullWrapped".to_string()), }),
"extend_types.includes[3]\n{:#?}", config
);

assert!(extend_types_includes.next().is_none(), "extend_types.includes[4]\n{:#?}", config);

let mut extend_types_excludes = extend_types.excludes.iter();
assert_eq!(extend_types_excludes.next(), None, "extend_types.excludes[0]\n{:#?}", config);
}
}
Loading

0 comments on commit 9c09c5b

Please sign in to comment.