bluejay 0.1.0.alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Cargo.lock +423 -0
- data/Cargo.toml +2 -0
- data/LICENSE +21 -0
- data/README.md +33 -0
- data/ext/Cargo.toml +17 -0
- data/ext/extconf.rb +6 -0
- data/ext/src/execution/coerce_result.rs +54 -0
- data/ext/src/execution/engine.rs +466 -0
- data/ext/src/execution/execution_error.rs +28 -0
- data/ext/src/execution/field_error.rs +8 -0
- data/ext/src/execution/key_store.rs +23 -0
- data/ext/src/execution.rs +10 -0
- data/ext/src/helpers/public_name.rs +21 -0
- data/ext/src/helpers/typed_frozen_r_array.rs +56 -0
- data/ext/src/helpers/wrapped_definition.rs +79 -0
- data/ext/src/helpers/wrapped_struct.rs +97 -0
- data/ext/src/helpers.rs +8 -0
- data/ext/src/lib.rs +10 -0
- data/ext/src/ruby_api/arguments_definition.rs +8 -0
- data/ext/src/ruby_api/coerce_input.rs +6 -0
- data/ext/src/ruby_api/coercion_error.rs +61 -0
- data/ext/src/ruby_api/custom_scalar_type_definition.rs +62 -0
- data/ext/src/ruby_api/enum_type_definition.rs +107 -0
- data/ext/src/ruby_api/enum_value_definition.rs +58 -0
- data/ext/src/ruby_api/enum_value_definitions.rs +8 -0
- data/ext/src/ruby_api/execution_error.rs +48 -0
- data/ext/src/ruby_api/execution_result.rs +40 -0
- data/ext/src/ruby_api/field_definition.rs +112 -0
- data/ext/src/ruby_api/fields_definition.rs +8 -0
- data/ext/src/ruby_api/input_fields_definition.rs +8 -0
- data/ext/src/ruby_api/input_object_type_definition.rs +138 -0
- data/ext/src/ruby_api/input_type_reference.rs +358 -0
- data/ext/src/ruby_api/input_value_definition.rs +98 -0
- data/ext/src/ruby_api/interface_implementation.rs +42 -0
- data/ext/src/ruby_api/interface_implementations.rs +8 -0
- data/ext/src/ruby_api/interface_type_definition.rs +82 -0
- data/ext/src/ruby_api/json_value.rs +111 -0
- data/ext/src/ruby_api/object_type_definition.rs +100 -0
- data/ext/src/ruby_api/output_type_reference.rs +238 -0
- data/ext/src/ruby_api/r_result.rs +84 -0
- data/ext/src/ruby_api/scalar.rs +45 -0
- data/ext/src/ruby_api/schema_definition.rs +270 -0
- data/ext/src/ruby_api/union_member_type.rs +41 -0
- data/ext/src/ruby_api/union_member_types.rs +8 -0
- data/ext/src/ruby_api/union_type_definition.rs +89 -0
- data/ext/src/ruby_api/validation_error.rs +63 -0
- data/ext/src/ruby_api.rs +75 -0
- data/lib/bluejay/base_input_type_reference.rb +13 -0
- data/lib/bluejay/base_output_type_reference.rb +15 -0
- data/lib/bluejay/custom_scalar_type.rb +40 -0
- data/lib/bluejay/enum_type.rb +44 -0
- data/lib/bluejay/ext.bundle +0 -0
- data/lib/bluejay/finalize.rb +27 -0
- data/lib/bluejay/input_type.rb +64 -0
- data/lib/bluejay/input_type_reference_shorthands.rb +28 -0
- data/lib/bluejay/interface_type.rb +60 -0
- data/lib/bluejay/json_value.rb +16 -0
- data/lib/bluejay/name_from_class.rb +18 -0
- data/lib/bluejay/object_type.rb +68 -0
- data/lib/bluejay/output_type_reference_shorthands.rb +28 -0
- data/lib/bluejay/schema.rb +63 -0
- data/lib/bluejay/union_type.rb +43 -0
- data/lib/bluejay/version.rb +5 -0
- data/lib/bluejay.rb +28 -0
- data/lib/rbi_ext/model.rb +64 -0
- data/lib/tapioca/dsl/compilers/input_type.rb +34 -0
- data/lib/tapioca/dsl/compilers/interface_type.rb +29 -0
- data/lib/tapioca/dsl/compilers/object_type.rb +43 -0
- data/lib/tapioca/dsl/compilers/schema.rb +42 -0
- 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
|
+
}
|