bluejay 0.1.0.alpha.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +7 -0
  2. data/Cargo.lock +423 -0
  3. data/Cargo.toml +2 -0
  4. data/LICENSE +21 -0
  5. data/README.md +33 -0
  6. data/ext/Cargo.toml +17 -0
  7. data/ext/extconf.rb +6 -0
  8. data/ext/src/execution/coerce_result.rs +54 -0
  9. data/ext/src/execution/engine.rs +466 -0
  10. data/ext/src/execution/execution_error.rs +28 -0
  11. data/ext/src/execution/field_error.rs +8 -0
  12. data/ext/src/execution/key_store.rs +23 -0
  13. data/ext/src/execution.rs +10 -0
  14. data/ext/src/helpers/public_name.rs +21 -0
  15. data/ext/src/helpers/typed_frozen_r_array.rs +56 -0
  16. data/ext/src/helpers/wrapped_definition.rs +79 -0
  17. data/ext/src/helpers/wrapped_struct.rs +97 -0
  18. data/ext/src/helpers.rs +8 -0
  19. data/ext/src/lib.rs +10 -0
  20. data/ext/src/ruby_api/arguments_definition.rs +8 -0
  21. data/ext/src/ruby_api/coerce_input.rs +6 -0
  22. data/ext/src/ruby_api/coercion_error.rs +61 -0
  23. data/ext/src/ruby_api/custom_scalar_type_definition.rs +62 -0
  24. data/ext/src/ruby_api/enum_type_definition.rs +107 -0
  25. data/ext/src/ruby_api/enum_value_definition.rs +58 -0
  26. data/ext/src/ruby_api/enum_value_definitions.rs +8 -0
  27. data/ext/src/ruby_api/execution_error.rs +48 -0
  28. data/ext/src/ruby_api/execution_result.rs +40 -0
  29. data/ext/src/ruby_api/field_definition.rs +112 -0
  30. data/ext/src/ruby_api/fields_definition.rs +8 -0
  31. data/ext/src/ruby_api/input_fields_definition.rs +8 -0
  32. data/ext/src/ruby_api/input_object_type_definition.rs +138 -0
  33. data/ext/src/ruby_api/input_type_reference.rs +358 -0
  34. data/ext/src/ruby_api/input_value_definition.rs +98 -0
  35. data/ext/src/ruby_api/interface_implementation.rs +42 -0
  36. data/ext/src/ruby_api/interface_implementations.rs +8 -0
  37. data/ext/src/ruby_api/interface_type_definition.rs +82 -0
  38. data/ext/src/ruby_api/json_value.rs +111 -0
  39. data/ext/src/ruby_api/object_type_definition.rs +100 -0
  40. data/ext/src/ruby_api/output_type_reference.rs +238 -0
  41. data/ext/src/ruby_api/r_result.rs +84 -0
  42. data/ext/src/ruby_api/scalar.rs +45 -0
  43. data/ext/src/ruby_api/schema_definition.rs +270 -0
  44. data/ext/src/ruby_api/union_member_type.rs +41 -0
  45. data/ext/src/ruby_api/union_member_types.rs +8 -0
  46. data/ext/src/ruby_api/union_type_definition.rs +89 -0
  47. data/ext/src/ruby_api/validation_error.rs +63 -0
  48. data/ext/src/ruby_api.rs +75 -0
  49. data/lib/bluejay/base_input_type_reference.rb +13 -0
  50. data/lib/bluejay/base_output_type_reference.rb +15 -0
  51. data/lib/bluejay/custom_scalar_type.rb +40 -0
  52. data/lib/bluejay/enum_type.rb +44 -0
  53. data/lib/bluejay/ext.bundle +0 -0
  54. data/lib/bluejay/finalize.rb +27 -0
  55. data/lib/bluejay/input_type.rb +64 -0
  56. data/lib/bluejay/input_type_reference_shorthands.rb +28 -0
  57. data/lib/bluejay/interface_type.rb +60 -0
  58. data/lib/bluejay/json_value.rb +16 -0
  59. data/lib/bluejay/name_from_class.rb +18 -0
  60. data/lib/bluejay/object_type.rb +68 -0
  61. data/lib/bluejay/output_type_reference_shorthands.rb +28 -0
  62. data/lib/bluejay/schema.rb +63 -0
  63. data/lib/bluejay/union_type.rb +43 -0
  64. data/lib/bluejay/version.rb +5 -0
  65. data/lib/bluejay.rb +28 -0
  66. data/lib/rbi_ext/model.rb +64 -0
  67. data/lib/tapioca/dsl/compilers/input_type.rb +34 -0
  68. data/lib/tapioca/dsl/compilers/interface_type.rb +29 -0
  69. data/lib/tapioca/dsl/compilers/object_type.rb +43 -0
  70. data/lib/tapioca/dsl/compilers/schema.rb +42 -0
  71. metadata +131 -0
@@ -0,0 +1,98 @@
1
+ use magnus::{function, Error, Module, Object, scan_args::get_kwargs, RHash, Value, TypedData, DataTypeFunctions, method};
2
+ use convert_case::{Casing, Case};
3
+ use super::{root, input_type_reference::InputTypeReference, coerce_input::CoerceInput, coercion_error::CoercionError, json_value::{JsonValue, JsonValueInner}};
4
+ use crate::helpers::WrappedStruct;
5
+
6
+ #[derive(Debug, TypedData)]
7
+ #[magnus(class = "Bluejay::InputValueDefinition", mark)]
8
+ pub struct InputValueDefinition {
9
+ name: String,
10
+ description: Option<String>,
11
+ r#type: WrappedStruct<InputTypeReference>,
12
+ default_value: Option<JsonValue>,
13
+ ruby_name: String,
14
+ }
15
+
16
+ impl InputValueDefinition {
17
+ pub fn new(kw: RHash) -> Result<Self, Error> {
18
+ let args = get_kwargs(kw, &["name", "type"], &["description", "default_value"])?;
19
+ let (name, r#type): (String, WrappedStruct<InputTypeReference>) = args.required;
20
+ let (description, default_value): (Option<Option<String>>, Option<JsonValue>) = args.optional;
21
+ let description = description.unwrap_or_default();
22
+ let _: () = args.splat;
23
+ let ruby_name = name.to_case(Case::Snake);
24
+ Ok(Self { name, description, r#type, default_value, ruby_name })
25
+ }
26
+
27
+ pub fn name(&self) -> &str {
28
+ self.name.as_str()
29
+ }
30
+
31
+ pub fn description(&self) -> Option<&str> {
32
+ self.description.as_ref().map(String::as_str)
33
+ }
34
+
35
+ pub fn r#type(&self) -> &InputTypeReference {
36
+ self.r#type.get()
37
+ }
38
+
39
+ pub fn default_value(&self) -> Option<Value> {
40
+ self.default_value.as_ref().map(|v| v.to_owned().into())
41
+ }
42
+
43
+ pub fn is_required(&self) -> bool {
44
+ if self.default_value.is_some() {
45
+ false
46
+ } else {
47
+ self.r#type.get().is_required()
48
+ }
49
+ }
50
+
51
+ fn ruby_name(&self) -> &str {
52
+ self.ruby_name.as_str()
53
+ }
54
+ }
55
+
56
+ impl DataTypeFunctions for InputValueDefinition {
57
+ fn mark(&self) {
58
+ self.r#type.mark();
59
+ }
60
+ }
61
+
62
+ impl CoerceInput for InputValueDefinition {
63
+ fn coerce_input(&self, value: Value, path: &[String]) -> Result<Result<Value, Vec<CoercionError>>, Error> {
64
+ self.r#type.get().coerce_input(value, path)
65
+ }
66
+ }
67
+
68
+ impl bluejay_core::definition::InputValueDefinition for InputValueDefinition {
69
+ type InputTypeReference = InputTypeReference;
70
+ type Value = JsonValueInner;
71
+
72
+ fn name(&self) -> &str {
73
+ self.name.as_str()
74
+ }
75
+
76
+ fn description(&self) -> Option<&str> {
77
+ self.description.as_ref().map(String::as_str)
78
+ }
79
+
80
+ fn r#type(&self) -> &Self::InputTypeReference {
81
+ self.r#type.get()
82
+ }
83
+
84
+ fn default_value(&self) -> Option<&Self::Value> {
85
+ self.default_value.as_ref().map(AsRef::as_ref)
86
+ }
87
+ }
88
+
89
+ pub fn init() -> Result<(), Error> {
90
+ let class = root().define_class("InputValueDefinition", Default::default())?;
91
+
92
+ class.define_singleton_method("new", function!(InputValueDefinition::new, 1))?;
93
+ class.define_method("name", method!(InputValueDefinition::name, 0))?;
94
+ class.define_method("type", method!(|ivd: &InputValueDefinition| ivd.r#type, 0))?;
95
+ class.define_method("ruby_name", method!(InputValueDefinition::ruby_name, 0))?;
96
+
97
+ Ok(())
98
+ }
@@ -0,0 +1,42 @@
1
+ use super::{root, interface_type_definition::InterfaceTypeDefinition};
2
+ use magnus::{RClass, function, Error, Module, Object, TypedData, DataTypeFunctions, method};
3
+ use crate::helpers::{WrappedDefinition, WrappedStruct};
4
+
5
+ #[derive(Clone, Debug, TypedData)]
6
+ #[magnus(class = "Bluejay::InterfaceImplementation", mark)]
7
+ pub struct InterfaceImplementation {
8
+ interface: WrappedDefinition<InterfaceTypeDefinition>,
9
+ }
10
+
11
+ impl InterfaceImplementation {
12
+ pub fn new(interface: RClass) -> Result<Self, Error> {
13
+ WrappedDefinition::new(interface).map(|interface| Self { interface })
14
+ }
15
+
16
+ pub fn interface(&self) -> WrappedStruct<InterfaceTypeDefinition> {
17
+ *self.interface.get()
18
+ }
19
+ }
20
+
21
+ impl DataTypeFunctions for InterfaceImplementation {
22
+ fn mark(&self) {
23
+ self.interface.mark();
24
+ }
25
+ }
26
+
27
+ impl bluejay_core::definition::InterfaceImplementation for InterfaceImplementation {
28
+ type InterfaceTypeDefinition = InterfaceTypeDefinition;
29
+
30
+ fn interface(&self) -> &Self::InterfaceTypeDefinition {
31
+ self.interface.as_ref()
32
+ }
33
+ }
34
+
35
+ pub fn init() -> Result<(), Error> {
36
+ let class = root().define_class("InterfaceImplementation", Default::default())?;
37
+
38
+ class.define_singleton_method("new", function!(InterfaceImplementation::new, 1))?;
39
+ class.define_method("interface", method!(|ii: &InterfaceImplementation| ii.interface.class(), 0))?;
40
+
41
+ Ok(())
42
+ }
@@ -0,0 +1,8 @@
1
+ use super::{interface_implementation::InterfaceImplementation};
2
+ use crate::helpers::{WrappedStruct, TypedFrozenRArray};
3
+
4
+ pub type InterfaceImplementations = TypedFrozenRArray<WrappedStruct<InterfaceImplementation>>;
5
+
6
+ impl bluejay_core::definition::InterfaceImplementations for InterfaceImplementations {
7
+ type InterfaceImplementation = InterfaceImplementation;
8
+ }
@@ -0,0 +1,82 @@
1
+ use magnus::{function, Error, Module, Object, scan_args::get_kwargs, RHash, memoize, TypedData, RArray, DataTypeFunctions, RClass, gc};
2
+ use super::{root, interface_implementations::InterfaceImplementations, fields_definition::FieldsDefinition};
3
+ use crate::helpers::HasDefinitionWrapper;
4
+
5
+ #[derive(Debug, TypedData)]
6
+ #[magnus(class = "Bluejay::InterfaceTypeDefinition", mark)]
7
+ pub struct InterfaceTypeDefinition {
8
+ name: String,
9
+ description: Option<String>,
10
+ fields_definition: FieldsDefinition,
11
+ interface_implementations: InterfaceImplementations,
12
+ }
13
+
14
+ impl InterfaceTypeDefinition {
15
+ fn new(kw: RHash) -> Result<Self, Error> {
16
+ let args = get_kwargs(kw, &["name", "field_definitions", "interface_implementations", "description"], &[])?;
17
+ let (name, field_definitions, interface_implementations, description): (String, RArray, RArray, Option<String>) = args.required;
18
+ let _: () = args.optional;
19
+ let _: () = args.splat;
20
+ let fields_definition = FieldsDefinition::new(field_definitions)?;
21
+ let interface_implementations = InterfaceImplementations::new(interface_implementations)?;
22
+ Ok(Self { name, description, fields_definition, interface_implementations })
23
+ }
24
+
25
+ pub fn name(&self) -> &str {
26
+ self.name.as_str()
27
+ }
28
+
29
+ pub fn description(&self) -> Option<&str> {
30
+ self.description.as_ref().map(String::as_str)
31
+ }
32
+
33
+ pub fn fields_definition(&self) -> &FieldsDefinition {
34
+ &self.fields_definition
35
+ }
36
+
37
+ pub fn interface_implementations(&self) -> &InterfaceImplementations {
38
+ &self.interface_implementations
39
+ }
40
+ }
41
+
42
+ impl DataTypeFunctions for InterfaceTypeDefinition {
43
+ fn mark(&self) {
44
+ gc::mark(self.fields_definition);
45
+ gc::mark(self.interface_implementations);
46
+ }
47
+ }
48
+
49
+ impl HasDefinitionWrapper for InterfaceTypeDefinition {
50
+ fn wrapping_class() -> RClass {
51
+ *memoize!(RClass: root().define_class("InterfaceType", Default::default()).unwrap())
52
+ }
53
+ }
54
+
55
+ impl bluejay_core::definition::InterfaceTypeDefinition for InterfaceTypeDefinition {
56
+ type FieldsDefinition = FieldsDefinition;
57
+ type InterfaceImplementations = InterfaceImplementations;
58
+
59
+ fn description(&self) -> Option<&str> {
60
+ self.description.as_ref().map(String::as_str)
61
+ }
62
+
63
+ fn name(&self) -> &str {
64
+ self.name.as_str()
65
+ }
66
+
67
+ fn fields_definition(&self) -> &Self::FieldsDefinition {
68
+ &self.fields_definition
69
+ }
70
+
71
+ fn interface_impelementations(&self) -> &Self::InterfaceImplementations {
72
+ &self.interface_implementations
73
+ }
74
+ }
75
+
76
+ pub fn init() -> Result<(), Error> {
77
+ let class = root().define_class("InterfaceTypeDefinition", Default::default())?;
78
+
79
+ class.define_singleton_method("new", function!(InterfaceTypeDefinition::new, 1))?;
80
+
81
+ Ok(())
82
+ }
@@ -0,0 +1,111 @@
1
+ use magnus::{Value, TryConvert, Error, Integer, Float, value::{Qtrue, Qfalse}, RString, RArray, RHash, r_hash::ForEach, exception, QNIL};
2
+
3
+ pub type JsonValueInner = bluejay_core::Value<true, String, i32, f64, String, bool, (), String, ListValue, ObjectValue>;
4
+
5
+ #[derive(Clone, Debug)]
6
+ pub struct ListValue(Vec<JsonValueInner>);
7
+
8
+ impl AsRef<[JsonValueInner]> for ListValue {
9
+ fn as_ref(&self) -> &[JsonValueInner] {
10
+ &self.0
11
+ }
12
+ }
13
+
14
+ impl bluejay_core::ListValue<JsonValueInner> for ListValue {}
15
+
16
+ impl Into<Value> for ListValue {
17
+ fn into(self) -> Value {
18
+ *RArray::from_iter(self.0.iter().map(|v| core_value_to_value(v.clone())))
19
+ }
20
+ }
21
+
22
+ #[derive(Clone, Debug)]
23
+ pub struct ObjectValue(Vec<(String, JsonValueInner)>);
24
+
25
+ impl bluejay_core::ObjectValue<JsonValueInner> for ObjectValue {
26
+ type Key = String;
27
+
28
+ fn fields(&self) -> &[(Self::Key, JsonValueInner)] {
29
+ &self.0
30
+ }
31
+ }
32
+
33
+ impl Into<Value> for ObjectValue {
34
+ fn into(self) -> Value {
35
+ *RHash::from_iter(self.0.iter().map(|(k, v)| (k.as_str(), core_value_to_value(v.clone()))))
36
+ }
37
+ }
38
+
39
+ #[derive(Clone, Debug)]
40
+ pub struct JsonValue(JsonValueInner);
41
+
42
+ impl AsRef<JsonValueInner> for JsonValue {
43
+ fn as_ref(&self) -> &JsonValueInner {
44
+ &self.0
45
+ }
46
+ }
47
+
48
+ impl TryConvert for JsonValue {
49
+ fn try_convert(val: Value) -> Result<Self, Error> {
50
+ // TODO: support BigDecimal or even better, Numeric
51
+ if let Some(i) = Integer::from_value(val) {
52
+ // TODO: reconcile if we need to handle integers bigger than 32 bits
53
+ // and if not, produce a better error for the user
54
+ Ok(JsonValue(JsonValueInner::Integer(i.to_i32()?)))
55
+ } else if let Some(f) = Float::from_value(val) {
56
+ Ok(JsonValue(JsonValueInner::Float(f.to_f64())))
57
+ } else if Qtrue::from_value(val).is_some() {
58
+ Ok(JsonValue(JsonValueInner::Boolean(true)))
59
+ } else if Qfalse::from_value(val).is_some() {
60
+ Ok(JsonValue(JsonValueInner::Boolean(false)))
61
+ } else if let Some(s) = RString::from_value(val) {
62
+ Ok(JsonValue(JsonValueInner::String(s.to_string()?)))
63
+ } else if val.is_nil() {
64
+ Ok(JsonValue(JsonValueInner::Null(())))
65
+ } else if let Some(arr) = RArray::from_value(val) {
66
+ let mut v: Vec<JsonValueInner> = Vec::new();
67
+ for el in arr.each() {
68
+ let json_value: Self = el?.try_convert()?;
69
+ v.push(json_value.0);
70
+ }
71
+ Ok(JsonValue(JsonValueInner::List(ListValue(v))))
72
+ } else if let Some(h) = RHash::from_value(val) {
73
+ let mut v: Vec<(String, JsonValueInner)> = Vec::new();
74
+ h.foreach(|key: String, value: Value| {
75
+ let json_value: Self = value.try_convert()?;
76
+ v.push((key, json_value.0));
77
+ Ok(ForEach::Continue)
78
+ })?;
79
+ Ok(JsonValue(JsonValueInner::Object(ObjectValue(v))))
80
+ } else {
81
+ Err(Error::new(
82
+ exception::type_error(),
83
+ format!(
84
+ "no implicit conversion of {} into JsonValue",
85
+ unsafe { val.classname() },
86
+ ),
87
+ ))
88
+ }
89
+ }
90
+ }
91
+
92
+ // TODO: get rid of this once input coercion is done by core crate
93
+ impl Into<Value> for JsonValue {
94
+ fn into(self) -> Value {
95
+ core_value_to_value(self.0)
96
+ }
97
+ }
98
+
99
+ fn core_value_to_value(core_value: JsonValueInner) -> Value {
100
+ match core_value {
101
+ JsonValueInner::Boolean(b) => b.into(),
102
+ JsonValueInner::String(s) => s.into(),
103
+ JsonValueInner::Integer(i) => i.into(),
104
+ JsonValueInner::Float(f) => f.into(),
105
+ JsonValueInner::Enum(e) => e.into(),
106
+ JsonValueInner::List(l) => l.into(),
107
+ JsonValueInner::Object(o) => o.into(),
108
+ JsonValueInner::Variable(_) => unreachable!(),
109
+ JsonValueInner::Null(_) => *QNIL,
110
+ }
111
+ }
@@ -0,0 +1,100 @@
1
+ use bluejay_core::AsIter;
2
+ use magnus::{function, Error, Module, Object, scan_args::get_kwargs, RHash, memoize, TypedData, RArray, DataTypeFunctions, RClass, method, gc};
3
+ use super::{root, field_definition::FieldDefinition, interface_implementations::InterfaceImplementations, interface_type_definition::InterfaceTypeDefinition, fields_definition::FieldsDefinition};
4
+ use crate::helpers::HasDefinitionWrapper;
5
+
6
+ #[derive(Debug, TypedData)]
7
+ #[magnus(class = "Bluejay::ObjectTypeDefinition", mark)]
8
+ pub struct ObjectTypeDefinition {
9
+ name: String,
10
+ description: Option<String>,
11
+ fields_definition: FieldsDefinition,
12
+ interface_implementations: InterfaceImplementations,
13
+ }
14
+
15
+ impl ObjectTypeDefinition {
16
+ fn new(kw: RHash) -> Result<Self, Error> {
17
+ let args = get_kwargs(kw, &["name", "field_definitions", "interface_implementations", "description"], &[])?;
18
+ let (name, field_definitions, interface_implementations, description): (String, RArray, RArray, Option<String>) = args.required;
19
+ let _: () = args.optional;
20
+ let _: () = args.splat;
21
+ field_definitions.push(FieldDefinition::typename())?;
22
+ let fields_definition = FieldsDefinition::new(field_definitions)?;
23
+ let interface_implementations = InterfaceImplementations::new(interface_implementations)?;
24
+ Ok(Self { name, description, fields_definition, interface_implementations })
25
+ }
26
+ }
27
+
28
+ impl DataTypeFunctions for ObjectTypeDefinition {
29
+ fn mark(&self) {
30
+ gc::mark(self.fields_definition);
31
+ gc::mark(self.interface_implementations);
32
+ }
33
+ }
34
+
35
+ impl HasDefinitionWrapper for ObjectTypeDefinition {
36
+ fn wrapping_class() -> RClass {
37
+ *memoize!(RClass: root().define_class("ObjectType", Default::default()).unwrap())
38
+ }
39
+ }
40
+
41
+ impl ObjectTypeDefinition {
42
+ pub fn name(&self) -> &str {
43
+ self.name.as_str()
44
+ }
45
+
46
+ pub fn description(&self) -> Option<&str> {
47
+ self.description.as_ref().map(String::as_str)
48
+ }
49
+
50
+ pub fn fields_definition(&self) -> &FieldsDefinition {
51
+ &self.fields_definition
52
+ }
53
+
54
+ pub fn interface_implementations(&self) -> &InterfaceImplementations {
55
+ &self.interface_implementations
56
+ }
57
+
58
+ pub fn implements_interface(&self, interface: &InterfaceTypeDefinition) -> bool {
59
+ self.interface_implementations
60
+ .iter()
61
+ .any(|ii| ii.interface().get().name() == interface.name())
62
+ }
63
+
64
+ pub fn field_definition(&self, name: &str) -> Option<&FieldDefinition> {
65
+ self.fields_definition
66
+ .iter()
67
+ .find(|fd| fd.name() == name)
68
+ }
69
+ }
70
+
71
+ impl bluejay_core::definition::ObjectTypeDefinition for ObjectTypeDefinition {
72
+ type FieldsDefinition = FieldsDefinition;
73
+ type InterfaceImplementations = InterfaceImplementations;
74
+
75
+ fn description(&self) -> Option<&str> {
76
+ self.description.as_ref().map(String::as_str)
77
+ }
78
+
79
+ fn name(&self) -> &str {
80
+ self.name.as_str()
81
+ }
82
+
83
+ fn fields_definition(&self) -> &Self::FieldsDefinition {
84
+ &self.fields_definition
85
+ }
86
+
87
+ fn interface_impelementations(&self) -> &Self::InterfaceImplementations {
88
+ &self.interface_implementations
89
+ }
90
+ }
91
+
92
+ pub fn init() -> Result<(), Error> {
93
+ let class = root().define_class("ObjectTypeDefinition", Default::default())?;
94
+
95
+ class.define_singleton_method("new", function!(ObjectTypeDefinition::new, 1))?;
96
+ class.define_method("name", method!(ObjectTypeDefinition::name, 0))?;
97
+ class.define_method("field_definitions", method!(|otd: &ObjectTypeDefinition| -> RArray { (*otd.fields_definition()).into() }, 0))?;
98
+
99
+ Ok(())
100
+ }
@@ -0,0 +1,238 @@
1
+ use magnus::{Error, Value, exception, TypedData, DataTypeFunctions, Module, scan_args::get_kwargs, RHash, Object, function, method};
2
+ use super::{root, enum_type_definition::EnumTypeDefinition, object_type_definition::ObjectTypeDefinition, union_type_definition::UnionTypeDefinition, custom_scalar_type_definition::CustomScalarTypeDefinition, scalar::Scalar, interface_type_definition::InterfaceTypeDefinition};
3
+ use crate::helpers::{WrappedStruct, WrappedDefinition};
4
+ use bluejay_core::definition::{OutputTypeReference as CoreOutputTypeReference};
5
+
6
+ #[derive(Clone, Debug)]
7
+ pub enum BaseOutputTypeReference {
8
+ BuiltinScalarType(bluejay_core::BuiltinScalarDefinition),
9
+ EnumType(WrappedDefinition<EnumTypeDefinition>),
10
+ ObjectType(WrappedDefinition<ObjectTypeDefinition>),
11
+ UnionType(WrappedDefinition<UnionTypeDefinition>),
12
+ InterfaceType(WrappedDefinition<InterfaceTypeDefinition>),
13
+ CustomScalarType(WrappedDefinition<CustomScalarTypeDefinition>),
14
+ }
15
+
16
+ impl bluejay_core::definition::AbstractBaseOutputTypeReference for BaseOutputTypeReference {
17
+ type CustomScalarTypeDefinition = CustomScalarTypeDefinition;
18
+ type EnumTypeDefinition = EnumTypeDefinition;
19
+ type ObjectTypeDefinition = ObjectTypeDefinition;
20
+ type InterfaceTypeDefinition = InterfaceTypeDefinition;
21
+ type UnionTypeDefinition = UnionTypeDefinition;
22
+ type WrappedCustomScalarTypeDefinition = WrappedStruct<CustomScalarTypeDefinition>;
23
+ type WrappedEnumTypeDefinition = WrappedStruct<EnumTypeDefinition>;
24
+ type WrappedObjectTypeDefinition = WrappedStruct<ObjectTypeDefinition>;
25
+ type WrappedInterfaceTypeDefinition = WrappedStruct<InterfaceTypeDefinition>;
26
+ type WrappedUnionTypeDefinition = WrappedStruct<UnionTypeDefinition>;
27
+
28
+ fn to_concrete(&self) -> bluejay_core::definition::BaseOutputTypeReferenceFromAbstract<Self> {
29
+ match self {
30
+ Self::BuiltinScalarType(bsd) => bluejay_core::definition::BaseOutputTypeReference::BuiltinScalarType(*bsd),
31
+ Self::EnumType(etd) => bluejay_core::definition::BaseOutputTypeReference::EnumType(*etd.get(), Default::default()),
32
+ Self::CustomScalarType(cstd) => bluejay_core::definition::BaseOutputTypeReference::CustomScalarType(*cstd.get(), Default::default()),
33
+ Self::ObjectType(otd) => bluejay_core::definition::BaseOutputTypeReference::ObjectType(*otd.get(), Default::default()),
34
+ Self::InterfaceType(itd) => bluejay_core::definition::BaseOutputTypeReference::InterfaceType(*itd.get(), Default::default()),
35
+ Self::UnionType(utd) => bluejay_core::definition::BaseOutputTypeReference::UnionType(*utd.get(), Default::default()),
36
+ }
37
+ }
38
+
39
+ fn name(&self) -> &str {
40
+ self.name()
41
+ }
42
+ }
43
+
44
+ impl BaseOutputTypeReference {
45
+ pub fn new(value: Value) -> Result<Self, Error> {
46
+ if let Ok(wrapped_struct) = value.try_convert::<WrappedStruct<Scalar>>() {
47
+ Ok(Self::BuiltinScalarType(wrapped_struct.get().to_owned().into()))
48
+ } else if let Ok(wrapped_definition) = value.try_convert() {
49
+ Ok(Self::EnumType(wrapped_definition))
50
+ } else if let Ok(wrapped_definition) = value.try_convert() {
51
+ Ok(Self::ObjectType(wrapped_definition))
52
+ } else if let Ok(wrapped_definition) = value.try_convert() {
53
+ Ok(Self::UnionType(wrapped_definition))
54
+ } else if let Ok(wrapped_definition) = value.try_convert() {
55
+ Ok(Self::InterfaceType(wrapped_definition))
56
+ } else if let Ok(wrapped_definition) = value.try_convert() {
57
+ Ok(Self::CustomScalarType(wrapped_definition))
58
+ } else {
59
+ Err(Error::new(
60
+ exception::type_error(),
61
+ format!(
62
+ "{} is not a valid output type",
63
+ value
64
+ ),
65
+ ))
66
+ }
67
+ }
68
+
69
+ pub fn mark(&self) {
70
+ match self {
71
+ Self::BuiltinScalarType(_) => {},
72
+ Self::ObjectType(wd) => wd.mark(),
73
+ Self::EnumType(wd) => wd.mark(),
74
+ Self::UnionType(wd) => wd.mark(),
75
+ Self::InterfaceType(wd) => wd.mark(),
76
+ Self::CustomScalarType(wd) => wd.mark(),
77
+ }
78
+ }
79
+
80
+ pub fn name(&self) -> &str {
81
+ match self {
82
+ Self::BuiltinScalarType(bstd) => bstd.name(),
83
+ Self::CustomScalarType(cstd) => cstd.as_ref().name(),
84
+ Self::EnumType(etd) => etd.as_ref().name(),
85
+ Self::InterfaceType(itd) => itd.as_ref().name(),
86
+ Self::ObjectType(otd) => otd.as_ref().name(),
87
+ Self::UnionType(utd) => utd.as_ref().name(),
88
+ }
89
+ }
90
+
91
+ fn sorbet_type(&self) -> String {
92
+ match self {
93
+ Self::BuiltinScalarType(bstd) => Scalar::from(*bstd).sorbet_type_fully_qualified_name().to_owned(),
94
+ Self::CustomScalarType(_) => "T.untyped".to_string(),
95
+ Self::EnumType(_) => "String".to_string(),
96
+ Self::InterfaceType(itd) => format!("{}::Interface", itd.fully_qualified_name()),
97
+ Self::ObjectType(otd) => format!("{}::Interface", otd.fully_qualified_name()),
98
+ Self::UnionType(utd) => utd.as_ref().sorbet_type()
99
+ }
100
+ }
101
+ }
102
+
103
+ #[derive(Clone, Debug, TypedData)]
104
+ #[magnus(class = "Bluejay::OutputTypeReference", mark)]
105
+ #[repr(transparent)]
106
+ pub struct OutputTypeReference(CoreOutputTypeReference<BaseOutputTypeReference, WrappedOutputTypeReference>);
107
+
108
+ impl AsRef<CoreOutputTypeReference<BaseOutputTypeReference, WrappedOutputTypeReference>> for OutputTypeReference {
109
+ fn as_ref(&self) -> &CoreOutputTypeReference<BaseOutputTypeReference, WrappedOutputTypeReference> {
110
+ &self.0
111
+ }
112
+ }
113
+
114
+ impl bluejay_core::definition::AbstractOutputTypeReference for OutputTypeReference {
115
+ type BaseOutputTypeReference = BaseOutputTypeReference;
116
+ type Wrapper = WrappedOutputTypeReference;
117
+ }
118
+
119
+ impl DataTypeFunctions for OutputTypeReference {
120
+ fn mark(&self) {
121
+ match &self.0 {
122
+ CoreOutputTypeReference::List(inner, _) => inner.mark(),
123
+ CoreOutputTypeReference::Base(inner, _) => inner.mark(),
124
+ }
125
+ }
126
+ }
127
+
128
+ impl From<CoreOutputTypeReference<BaseOutputTypeReference, WrappedOutputTypeReference>> for OutputTypeReference {
129
+ fn from(value: CoreOutputTypeReference<BaseOutputTypeReference, WrappedOutputTypeReference>) -> Self {
130
+ Self(value)
131
+ }
132
+ }
133
+
134
+ #[derive(Clone, Debug)]
135
+ #[repr(transparent)]
136
+ pub struct WrappedOutputTypeReference(WrappedStruct<OutputTypeReference>);
137
+
138
+ impl AsRef<CoreOutputTypeReference<BaseOutputTypeReference, Self>> for WrappedOutputTypeReference {
139
+ fn as_ref(&self) -> &CoreOutputTypeReference<BaseOutputTypeReference, Self> {
140
+ self.0.get().as_ref()
141
+ }
142
+ }
143
+
144
+ impl WrappedOutputTypeReference {
145
+ fn mark(&self) {
146
+ self.0.mark()
147
+ }
148
+
149
+ pub fn get(&self) -> &OutputTypeReference {
150
+ self.0.get()
151
+ }
152
+ }
153
+
154
+ impl From<WrappedStruct<OutputTypeReference>> for WrappedOutputTypeReference {
155
+ fn from(value: WrappedStruct<OutputTypeReference>) -> Self {
156
+ Self(value)
157
+ }
158
+ }
159
+
160
+ impl From<OutputTypeReference> for WrappedOutputTypeReference {
161
+ fn from(value: OutputTypeReference) -> Self {
162
+ Self(WrappedStruct::wrap(value))
163
+ }
164
+ }
165
+
166
+ impl AsRef<WrappedStruct<OutputTypeReference>> for WrappedOutputTypeReference {
167
+ fn as_ref(&self) -> &WrappedStruct<OutputTypeReference> {
168
+ &self.0
169
+ }
170
+ }
171
+
172
+ impl OutputTypeReference {
173
+ pub fn new(kw: RHash) -> Result<Self, Error> {
174
+ let args = get_kwargs(kw, &["type", "required"], &[])?;
175
+ let (r#type, required): (Value, bool) = args.required;
176
+ let _: () = args.optional;
177
+ let _: () = args.splat;
178
+ let base = BaseOutputTypeReference::new(r#type)?;
179
+ Ok(Self(CoreOutputTypeReference::Base(base, required)))
180
+ }
181
+
182
+ pub fn list(kw: RHash) -> Result<Self, Error> {
183
+ let args = get_kwargs(kw, &["type", "required"], &[])?;
184
+ let (r#type, required): (WrappedStruct<Self>, bool) = args.required;
185
+ let _: () = args.optional;
186
+ let _: () = args.splat;
187
+ Ok(Self(CoreOutputTypeReference::List(r#type.into(), required)))
188
+ }
189
+
190
+ fn is_list(&self) -> bool {
191
+ matches!(&self.0, CoreOutputTypeReference::List(_, _))
192
+ }
193
+
194
+ fn is_base(&self) -> bool {
195
+ matches!(&self.0, CoreOutputTypeReference::Base(_, _))
196
+ }
197
+
198
+ fn is_required(&self) -> bool {
199
+ self.0.is_required()
200
+ }
201
+
202
+ fn unwrap_list(&self) -> Result<WrappedStruct<OutputTypeReference>, Error> {
203
+ match &self.0 {
204
+ CoreOutputTypeReference::List(inner, _) => Ok(*inner.as_ref()),
205
+ CoreOutputTypeReference::Base(_, _) => Err(Error::new(
206
+ exception::runtime_error(),
207
+ "Tried to unwrap a non-list OutputTypeReference".to_owned(),
208
+ )),
209
+ }
210
+ }
211
+
212
+ fn sorbet_type(&self) -> String {
213
+ let is_required = self.0.is_required();
214
+ let inner = match &self.0 {
215
+ CoreOutputTypeReference::List(inner, _) => format!("T::Array[{}]", inner.get().sorbet_type()),
216
+ CoreOutputTypeReference::Base(base, _) => base.sorbet_type(),
217
+ };
218
+ if is_required {
219
+ inner
220
+ } else {
221
+ format!("T.nilable({})", inner)
222
+ }
223
+ }
224
+ }
225
+
226
+ pub fn init() -> Result<(), Error> {
227
+ let class = root().define_class("OutputTypeReference", Default::default())?;
228
+
229
+ class.define_singleton_method("new", function!(OutputTypeReference::new, 1))?;
230
+ class.define_singleton_method("list", function!(OutputTypeReference::list, 1))?;
231
+ class.define_method("list?", method!(OutputTypeReference::is_list, 0))?;
232
+ class.define_method("base?", method!(OutputTypeReference::is_base, 0))?;
233
+ class.define_method("required?", method!(OutputTypeReference::is_required, 0))?;
234
+ class.define_method("sorbet_type", method!(OutputTypeReference::sorbet_type, 0))?;
235
+ class.define_method("unwrap_list", method!(OutputTypeReference::unwrap_list, 0))?;
236
+
237
+ Ok(())
238
+ }