bluejay 0.1.0.alpha.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
}
|