Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: start work on uuid support #411

Draft
wants to merge 41 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
f22d276
feat: start work on uuid
iamwacko Jan 20, 2023
f362683
feat: more work on uuid
iamwacko Jan 21, 2023
1320828
fix: use preludes
iamwacko Jan 21, 2023
ffd6178
fix: underscores and non-exhaustive patterns
iamwacko Jan 21, 2023
1879e27
fix: clippy complaints
iamwacko Jan 21, 2023
69b7baf
fix: datasource
iamwacko Jan 21, 2023
7e4d320
fix: non-exhaustive patterns
iamwacko Jan 21, 2023
b40afb5
chore: clippy
iamwacko Jan 21, 2023
88c1bd6
docs: changed UUID to be seperate
iamwacko Jan 21, 2023
6f3fcb9
docs: change examples to uuid
iamwacko Jan 21, 2023
5b3cf2c
docs: fix trailing comma
iamwacko Jan 21, 2023
4c20e04
docs: more uuid doc stuff
iamwacko Jan 21, 2023
167434b
docs: more docs things
iamwacko Jan 21, 2023
f56d010
fix: change tests to work with new uuid
iamwacko Jan 21, 2023
f385694
fix: change error message for string subtypes
iamwacko Jan 21, 2023
fbf75cb
fix: tests changed
iamwacko Jan 21, 2023
2704c93
fix: change schema for tests
iamwacko Jan 21, 2023
599f434
fix: hidden:true
iamwacko Jan 21, 2023
be6ecc2
fix: test, maybe
iamwacko Jan 21, 2023
5cbdbc9
test: added uuid to tests
iamwacko Jan 22, 2023
3432858
fix: typo in code
iamwacko Jan 22, 2023
28ee346
fix: hopefully
iamwacko Jan 22, 2023
80202f7
fix: debug errors
iamwacko Feb 10, 2023
96563bf
chore: added more annotations to help with debugging
iamwacko Feb 10, 2023
e99f90c
fix: Clone not implemented
iamwacko Feb 10, 2023
8f699fa
chore: derive debug
iamwacko Feb 10, 2023
dd55cae
fix: conflicting implementations
iamwacko Feb 10, 2023
b7eef8e
chore: add debug to generic trait bound
iamwacko Feb 10, 2023
4a98de9
chore: revert new trait bound
iamwacko Feb 10, 2023
fc75bf7
chore: associated type trait bound
iamwacko Feb 10, 2023
387bff7
chore: change to move to not use impl trait
iamwacko Feb 10, 2023
8dfaff5
chore: make things work
iamwacko Feb 10, 2023
7a2b278
chore: does where work for struct definitions
iamwacko Feb 10, 2023
45f3f37
chore: added comma
iamwacko Feb 10, 2023
98db275
chore: changed location of where
iamwacko Feb 10, 2023
62036a7
chore: removed Debug notation
iamwacko Feb 10, 2023
fcb5b51
chore: removed Debug notation
iamwacko Feb 10, 2023
6f614eb
chore: update deps to fix compiles
iamwacko Apr 19, 2023
7fbd2ad
Merge branch 'master' into uuid_support
iamwacko Apr 19, 2023
708fe80
chore: more work on uuid support
iamwacko Apr 20, 2023
2c088a3
chore: cargo fmt
iamwacko Apr 20, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ bincode = "1.3.1"
num = { version = "0.4.0", features = [ "rand" ] }
rand_regex = "0.15.1"
synth-gen = { path = "../gen", features = [ "shared" ] }
uuid = { version = "0.8.2", features = ["v4"] }
uuid = { version = "1.2.2", features = ["v4", "serde"] }
bimap = { version = "0.6.0", features = [ "std" ] }
humantime-serde = "1.0.1"
bloomfilter = "1.0.5"
dynfmt = { version = "0.1.5", features = [ "curly" ] }
sqlx = { version = "0.6", features = ["postgres", "mysql", "runtime-async-std-rustls", "decimal", "chrono"] }
sqlx = { version = "0.6", features = ["postgres", "mysql", "runtime-async-std-rustls", "decimal", "chrono", "uuid"] }
uriparse = "0.6.3"
paste = "1.0"
9 changes: 9 additions & 0 deletions core/src/compile/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,15 @@ pub mod tests {
assert!(complete(generator).unwrap().as_bool().unwrap())
}

#[test]
fn compile_uuid() {
let generator = generator! ({
"type": "uuid"
});
let value = complete(generator).unwrap();
assert!(value.is_uuid())
}

#[test]
fn compile_linear() {
let generator = generator!({
Expand Down
1 change: 1 addition & 0 deletions core/src/graph/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ pub fn synth_val_to_json(val: Value) -> serde_json::Value {
Value::Bool(b) => serde_json::Value::Bool(b),
Value::Number(n) => serde_json::Value::Number(synth_num_to_json(n)),
Value::String(s) => serde_json::Value::String(s),
Value::Uuid(u) => serde_json::Value::String(u.hyphenated().to_string()),
Value::DateTime(dt) => serde_json::Value::String(dt.format_to_string()),
Value::Object(obj) => serde_json::Value::Object(synth_obj_to_json(obj)),
Value::Array(arr) => serde_json::Value::Array(synth_arr_to_json(arr)),
Expand Down
32 changes: 31 additions & 1 deletion core/src/graph/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::collections::BTreeMap;

use anyhow::{Context, Result};

use ::uuid::Uuid;
use chrono::{DateTime, FixedOffset, NaiveDate, NaiveDateTime, NaiveTime, Utc};
use sqlx::mysql::MySqlTypeInfo;
use sqlx::postgres::{PgArgumentBuffer, PgTypeInfo};
Expand All @@ -23,7 +24,10 @@ pub mod null;
pub use null::NullNode;

pub mod string;
pub use string::{Format, FormatArgs, RandFaker, RandomString, StringNode, Truncated, UuidGen};
pub use string::{Format, FormatArgs, RandFaker, RandomString, StringNode, Truncated};

pub mod uuid;
pub use self::uuid::UuidNode;

pub mod date_time;
pub use date_time::{DateTimeNode, RandomDateTime};
Expand Down Expand Up @@ -161,6 +165,7 @@ derive_from! {
Bool(bool),
Number(Number),
String(String),
Uuid(Uuid),
DateTime(ChronoValueAndFormat),
Object(BTreeMap<String, Value>),
Array(Vec<Value>),
Expand Down Expand Up @@ -317,6 +322,7 @@ impl TryFrom<Value> for String {
Value::String(str) => Ok(str),
Value::Number(num) => Ok(num.to_string()),
Value::DateTime(date) => Ok(date.format_to_string()),
Value::Uuid(u) => Ok(u.hyphenated().to_string()),
otherwise => Err(failed_crate!(
target: Release,
"invalid type: expected 'String', found '{}'",
Expand Down Expand Up @@ -397,6 +403,7 @@ impl Value {
Self::Object(_) => {
serde_json::to_string(&json::synth_val_to_json(self.clone())).unwrap()
}
Self::Uuid(uid) => uid.hyphenated().to_string(),
}
}

Expand All @@ -409,6 +416,7 @@ impl Value {
// Based on https://docs.rs/sqlx-core/0.5.9/sqlx_core/postgres/types/index.html
while let Some(c) = current {
let pair = match c {
Value::Uuid(_) => (None, "uuid"),
Value::Null(_) => (None, "unknown"),
Value::Bool(_) => (None, "bool"),
Value::Number(num) => match *num {
Expand Down Expand Up @@ -501,6 +509,7 @@ impl Encode<'_, Postgres> for Value {
json::synth_val_to_json(self.clone()),
buf,
),
Value::Uuid(u) => <Uuid as Encode<'_, Postgres>>::encode_by_ref(u, buf),
Value::Array(_) => {
let s = self.to_postgres_string();
<String as Encode<'_, Postgres>>::encode_by_ref(&s, buf)
Expand Down Expand Up @@ -553,6 +562,7 @@ impl Encode<'_, MySql> for Value {
buf,
),
Value::Array(_arr) => todo!(), //<Vec<Value> as Encode<'_, MySql>>::encode_by_ref(arr, buf), //TODO special-case for u8 arrays?
Value::Uuid(u) => <Uuid as Encode<'_, MySql>>::encode_by_ref(u, buf),
}
}

Expand Down Expand Up @@ -583,6 +593,7 @@ impl Encode<'_, MySql> for Value {
ChronoValue::DateTime(_) => <DateTime<Utc> as Type<MySql>>::type_info(),
},
Value::String(_) => <String as Type<MySql>>::type_info(),
Value::Uuid(_) => <Uuid as Type<MySql>>::type_info(),
Value::Object(_) => return None, //TODO: Use JSON here?
Value::Array(elems) => {
if elems.is_empty() {
Expand Down Expand Up @@ -623,6 +634,10 @@ impl Value {
self.as_object().is_some()
}

pub fn is_uuid(&self) -> bool {
self.as_uuid().is_some()
}

pub fn is_array(&self) -> bool {
self.as_array().is_some()
}
Expand Down Expand Up @@ -669,6 +684,13 @@ impl Value {
}
}

pub fn as_uuid(&self) -> Option<&Uuid> {
match *self {
Value::Uuid(ref u) => Some(u),
_ => None,
}
}

pub fn as_array(&self) -> Option<&Vec<Value>> {
match *self {
Value::Array(ref vec) => Some(vec),
Expand Down Expand Up @@ -714,6 +736,13 @@ impl Value {
}
}

pub fn as_uuid_mut(&mut self) -> Option<&mut Uuid> {
match *self {
Value::Uuid(ref mut u) => Some(u),
_ => None,
}
}

pub fn as_array_mut(&mut self) -> Option<&mut Vec<Value>> {
match *self {
Value::Array(ref mut vec) => Some(vec),
Expand Down Expand Up @@ -777,6 +806,7 @@ derive_generator!(
DateTime(DateTimeNode),
Object(ObjectNode),
Array(ArrayNode),
Uuid(UuidNode),
OneOf(OneOfNode),
Series(SeriesNode),
Unique(UniqueNode),
Expand Down
9 changes: 0 additions & 9 deletions core/src/graph/string/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ pub mod format;
pub mod serialized;
pub mod sliced;
pub mod truncated;
pub mod uuid;

pub use self::uuid::UuidGen;
pub use constant::Constant;
pub use faker::{FakerArgs, Locale, RandFaker};
pub use format::{Format, FormatArgs};
Expand All @@ -26,7 +24,6 @@ derive_generator! {
Faker(TryOnce<RandFaker>),
Serialized(TryOnce<Serialized>)
Categorical(OnceInfallible<Random<String, Categorical<String>>>)
Uuid(OnceInfallible<UuidGen>),
Format(Format),
Truncated(Truncated),
Sliced(Sliced),
Expand Down Expand Up @@ -58,12 +55,6 @@ impl From<Categorical<String>> for RandomString {
}
}

impl From<UuidGen> for RandomString {
fn from(uuid: UuidGen) -> Self {
Self::Uuid(uuid.infallible().try_once())
}
}

impl From<Truncated> for RandomString {
fn from(trunc: Truncated) -> Self {
Self::Truncated(trunc)
Expand Down
15 changes: 0 additions & 15 deletions core/src/graph/string/uuid.rs

This file was deleted.

26 changes: 26 additions & 0 deletions core/src/graph/uuid.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use super::prelude::*;
use uuid::Uuid;

derive_generator! {
yield Token,
return Result<Value, Error>,
pub struct UuidNode(Valuize<Tokenizer<RandomUuid>, Uuid>);
}

impl From<RandomUuid> for UuidNode {
fn from(value: RandomUuid) -> Self {
Self(value.into_token().map_complete(value_from_ok::<Uuid>))
}
}

pub struct RandomUuid {}

impl Generator for RandomUuid {
type Yield = Token;
type Return = Result<Uuid, Error>;

fn next<R: Rng>(&mut self, rng: &mut R) -> GeneratorState<Self::Yield, Self::Return> {
let uuid = Uuid::from_u128(rng.gen());
GeneratorState::Complete(Ok(uuid))
}
}
15 changes: 10 additions & 5 deletions core/src/schema/content/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pub use number::{number_content, NumberContent, NumberContentKind, NumberKindExt
mod string;
pub use string::{
ConstantContent, FakerContent, FakerContentArgument, FormatContent, RegexContent,
SlicedContent, StringContent, Uuid,
SlicedContent, StringContent,
};

mod date_time;
Expand All @@ -44,6 +44,9 @@ pub use array::ArrayContent;
mod object;
pub use object::ObjectContent;

mod uuid;
pub use self::uuid::UuidContent;

mod datasource;
pub use datasource::DatasourceContent;

Expand Down Expand Up @@ -305,9 +308,10 @@ content! {
labels: ContentLabels,
variants: {
Null(NullContent) => None,
Uuid(UuidContent) => None,
Bool(BoolContent) => "missing a subtype. Try adding `constant`, or `frequency`",
Number(NumberContent) => "missing a subtype. Try adding `constant`, `range`, or `id`",
String(StringContent) => "missing a subtype. Try adding `pattern`, `faker`, `categorical`, `serialized`, `uuid`, `truncated`, or `format`",
String(StringContent) => "missing a subtype. Try adding `pattern`, `faker`, `categorical`, `serialized`, `truncated`, or `format`",
DateTime(DateTimeContent) => "missing a `format` field",
Array(ArrayContent) => "missing a `length` and `content` field",
Object(ObjectContent) => None,
Expand Down Expand Up @@ -498,6 +502,7 @@ impl Content {

pub fn kind(&self) -> String {
match self {
Content::Uuid(_) => "uuid".to_string(),
Content::Null(_) => "null".to_string(),
Content::Bool(content) => format!("bool::{}", content.kind()),
Content::Number(content) => format!("number::{}", content.kind()),
Expand Down Expand Up @@ -632,6 +637,7 @@ impl Compile for Content {
Self::Object(object_content) => object_content.compile(compiler),
Self::Bool(bool_content) => bool_content.compile(compiler),
Self::String(string_content) => string_content.compile(compiler),
Self::Uuid(uuid_content) => uuid_content.compile(compiler),
Self::DateTime(date_time_content) => date_time_content.compile(compiler),
Self::Number(number_content) => number_content.compile(compiler),
Self::Array(array_content) => array_content.compile(compiler),
Expand Down Expand Up @@ -705,8 +711,7 @@ pub mod tests {
"type": "object",
"skip_when_null": true,
"_uuid": {
"type": "string",
"uuid": {},
"type": "uuid",
"hidden": true
},
"user_id": {
Expand Down Expand Up @@ -901,7 +906,7 @@ pub mod tests {

#[test]
#[should_panic(
expected = "`string` generator is missing a subtype. Try adding `pattern`, `faker`, `categorical`, `serialized`, `uuid`, `truncated`, or `format`"
expected = "`string` generator is missing a subtype. Try adding `pattern`, `faker`, `categorical`, `serialized`, `truncated`, or `format`"
)]
fn string_missing_subtype() {
let _schema: Content = schema!({
Expand Down
6 changes: 0 additions & 6 deletions core/src/schema/content/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,19 @@ pub enum StringContent {
Faker(FakerContent),
Categorical(Categorical<String>),
Serialized(SerializedContent),
Uuid(Uuid),
Truncated(TruncatedContent),
Sliced(SlicedContent),
Format(FormatContent),
Constant(ConstantContent),
}

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash)]
pub struct Uuid;

impl StringContent {
pub fn kind(&self) -> String {
match self {
Self::Pattern(_) => "pattern".to_string(),
Self::Faker(faker) => faker.kind(),
Self::Categorical(_) => "categorical".to_string(),
Self::Serialized(_) => "serialized".to_string(),
Self::Uuid(_) => "uuid".to_string(),
Self::Truncated(_) => "truncated".to_string(),
Self::Sliced(_) => "sliced".to_string(),
Self::Constant(_) => "constant".to_string(),
Expand Down Expand Up @@ -352,7 +347,6 @@ impl Compile for StringContent {
StringContent::Constant(ConstantContent(s)) => {
RandomString::from(Constant(s.into())).into()
}
StringContent::Uuid(_uuid) => RandomString::from(UuidGen {}).into(),
};
Ok(Graph::String(string_node))
}
Expand Down
14 changes: 14 additions & 0 deletions core/src/schema/content/uuid.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use super::prelude::*;
use crate::graph::uuid::RandomUuid;

#[derive(Default, Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash)]
#[serde(rename_all = "snake_case")]
#[serde(deny_unknown_fields)]
pub struct UuidContent {}

impl Compile for UuidContent {
fn compile<'a, C: Compiler<'a>>(&'a self, mut _compiler: C) -> Result<Graph> {
let random_uuid = RandomUuid {};
Ok(Graph::Uuid(random_uuid.into()))
}
}
1 change: 0 additions & 1 deletion core/src/schema/inference/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,6 @@ impl MergeStrategy<StringContent, String> for OptionalMergeStrategy {
}
StringContent::Faker(_) => Ok(()),
StringContent::Serialized(_) => Ok(()), // we can probably do better here
StringContent::Uuid(_) => Ok(()),
StringContent::Truncated(_) => Ok(()),
StringContent::Sliced(_) => Ok(()),
StringContent::Constant(_) => Ok(()),
Expand Down
Loading