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,79 @@
|
|
1
|
+
use once_cell::unsync::OnceCell;
|
2
|
+
use magnus::{RClass, TypedData, Error, Module, exception, gc, TryConvert, Value};
|
3
|
+
use super::WrappedStruct;
|
4
|
+
|
5
|
+
pub trait HasDefinitionWrapper: TypedData {
|
6
|
+
fn wrapping_class() -> RClass;
|
7
|
+
}
|
8
|
+
|
9
|
+
#[derive(Debug)]
|
10
|
+
pub struct WrappedDefinition<T: HasDefinitionWrapper> {
|
11
|
+
cls: RClass,
|
12
|
+
memoized_definition: OnceCell<WrappedStruct<T>>,
|
13
|
+
}
|
14
|
+
|
15
|
+
impl<T: HasDefinitionWrapper> Clone for WrappedDefinition<T> {
|
16
|
+
fn clone(&self) -> Self {
|
17
|
+
Self { cls: self.cls.clone(), memoized_definition: self.memoized_definition.clone() }
|
18
|
+
}
|
19
|
+
}
|
20
|
+
|
21
|
+
impl<T: HasDefinitionWrapper> WrappedDefinition<T> {
|
22
|
+
pub fn new(cls: RClass) -> Result<Self, Error> {
|
23
|
+
if cls.is_inherited(T::wrapping_class()) {
|
24
|
+
Ok(Self { cls, memoized_definition: OnceCell::new() })
|
25
|
+
} else {
|
26
|
+
Err(Error::new(
|
27
|
+
exception::type_error(),
|
28
|
+
format!(
|
29
|
+
"no implicit conversion of {} into {}",
|
30
|
+
cls,
|
31
|
+
T::wrapping_class()
|
32
|
+
),
|
33
|
+
))
|
34
|
+
}
|
35
|
+
}
|
36
|
+
|
37
|
+
pub fn get(&self) -> &WrappedStruct<T> {
|
38
|
+
self.memoized_definition
|
39
|
+
.get_or_init(|| self.cls.funcall("definition", ()).unwrap())
|
40
|
+
}
|
41
|
+
|
42
|
+
pub fn mark(&self) {
|
43
|
+
gc::mark(self.cls);
|
44
|
+
if let Some(ws) = self.memoized_definition.get() {
|
45
|
+
ws.mark();
|
46
|
+
}
|
47
|
+
}
|
48
|
+
|
49
|
+
pub fn fully_qualified_name(&self) -> String {
|
50
|
+
unsafe { self.cls.name() }.into_owned()
|
51
|
+
}
|
52
|
+
|
53
|
+
pub fn class(&self) -> RClass {
|
54
|
+
self.cls
|
55
|
+
}
|
56
|
+
}
|
57
|
+
|
58
|
+
impl<T: HasDefinitionWrapper> TryConvert for WrappedDefinition<T> {
|
59
|
+
fn try_convert(val: Value) -> Result<Self, Error> {
|
60
|
+
let cls = RClass::from_value(val).ok_or_else(|| {
|
61
|
+
Error::new(
|
62
|
+
exception::type_error(),
|
63
|
+
format!(
|
64
|
+
"no implicit conversion of {} into {}",
|
65
|
+
unsafe { val.classname() },
|
66
|
+
T::wrapping_class()
|
67
|
+
),
|
68
|
+
)
|
69
|
+
})?;
|
70
|
+
|
71
|
+
Self::new(cls)
|
72
|
+
}
|
73
|
+
}
|
74
|
+
|
75
|
+
impl<T: HasDefinitionWrapper> AsRef<T> for WrappedDefinition<T> {
|
76
|
+
fn as_ref(&self) -> &T {
|
77
|
+
self.get().as_ref()
|
78
|
+
}
|
79
|
+
}
|
@@ -0,0 +1,97 @@
|
|
1
|
+
use magnus::{error::Error, exception, gc, value::Value, RTypedData, TryConvert, TypedData};
|
2
|
+
use std::{marker::PhantomData, ops::Deref};
|
3
|
+
|
4
|
+
/// A small wrapper for `RTypedData` that keeps track of the concrete struct
|
5
|
+
/// type, and the underlying [`Value`] for GC purposes.
|
6
|
+
#[derive(Debug)]
|
7
|
+
#[repr(transparent)]
|
8
|
+
pub struct WrappedStruct<T: TypedData> {
|
9
|
+
inner: RTypedData,
|
10
|
+
phantom: PhantomData<T>,
|
11
|
+
}
|
12
|
+
|
13
|
+
impl<T: TypedData> Copy for WrappedStruct<T> {}
|
14
|
+
|
15
|
+
impl<T: TypedData> Clone for WrappedStruct<T> {
|
16
|
+
fn clone(&self) -> Self {
|
17
|
+
*self
|
18
|
+
}
|
19
|
+
}
|
20
|
+
|
21
|
+
impl<T: TypedData> WrappedStruct<T> {
|
22
|
+
/// Gets the underlying struct.
|
23
|
+
pub fn get(&self) -> &T {
|
24
|
+
self.inner.get().unwrap()
|
25
|
+
}
|
26
|
+
|
27
|
+
/// Get the Ruby [`Value`] for this struct.
|
28
|
+
pub fn to_value(&self) -> Value {
|
29
|
+
self.inner.into()
|
30
|
+
}
|
31
|
+
|
32
|
+
/// Marks the Ruby [`Value`] for GC.
|
33
|
+
pub fn mark(&self) {
|
34
|
+
gc::mark(&self.inner.into());
|
35
|
+
}
|
36
|
+
|
37
|
+
pub fn wrap(data: T) -> Self {
|
38
|
+
let inner = RTypedData::wrap(data);
|
39
|
+
Self {
|
40
|
+
inner,
|
41
|
+
phantom: PhantomData,
|
42
|
+
}
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
impl<T: TypedData> From<WrappedStruct<T>> for Value {
|
47
|
+
fn from(wrapped_struct: WrappedStruct<T>) -> Self {
|
48
|
+
wrapped_struct.to_value()
|
49
|
+
}
|
50
|
+
}
|
51
|
+
|
52
|
+
impl<T: TypedData> Deref for WrappedStruct<T> {
|
53
|
+
type Target = RTypedData;
|
54
|
+
|
55
|
+
fn deref(&self) -> &Self::Target {
|
56
|
+
&self.inner
|
57
|
+
}
|
58
|
+
}
|
59
|
+
|
60
|
+
impl<T: TypedData> From<T> for WrappedStruct<T> {
|
61
|
+
fn from(t: T) -> Self {
|
62
|
+
Self {
|
63
|
+
inner: RTypedData::wrap(t).into(),
|
64
|
+
phantom: PhantomData,
|
65
|
+
}
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
69
|
+
impl<T> TryConvert for WrappedStruct<T>
|
70
|
+
where
|
71
|
+
T: TypedData,
|
72
|
+
{
|
73
|
+
fn try_convert(val: Value) -> Result<Self, Error> {
|
74
|
+
let inner = RTypedData::from_value(val).ok_or_else(|| {
|
75
|
+
Error::new(
|
76
|
+
exception::type_error(),
|
77
|
+
format!(
|
78
|
+
"no implicit conversion of {} into {}",
|
79
|
+
unsafe { val.classname() },
|
80
|
+
T::class()
|
81
|
+
),
|
82
|
+
)
|
83
|
+
})?;
|
84
|
+
inner.get::<T>()?;
|
85
|
+
|
86
|
+
Ok(Self {
|
87
|
+
inner,
|
88
|
+
phantom: PhantomData,
|
89
|
+
})
|
90
|
+
}
|
91
|
+
}
|
92
|
+
|
93
|
+
impl<T: TypedData> AsRef<T> for WrappedStruct<T> {
|
94
|
+
fn as_ref(&self) -> &T {
|
95
|
+
self.get()
|
96
|
+
}
|
97
|
+
}
|
data/ext/src/helpers.rs
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
mod wrapped_definition;
|
2
|
+
pub use wrapped_definition::{HasDefinitionWrapper, WrappedDefinition};
|
3
|
+
mod public_name;
|
4
|
+
pub use public_name::public_name;
|
5
|
+
mod typed_frozen_r_array;
|
6
|
+
pub use typed_frozen_r_array::TypedFrozenRArray;
|
7
|
+
mod wrapped_struct;
|
8
|
+
pub use wrapped_struct::WrappedStruct;
|
data/ext/src/lib.rs
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
use super::{input_value_definition::InputValueDefinition};
|
2
|
+
use crate::helpers::{WrappedStruct, TypedFrozenRArray};
|
3
|
+
|
4
|
+
pub type ArgumentsDefinition = TypedFrozenRArray<WrappedStruct<InputValueDefinition>>;
|
5
|
+
|
6
|
+
impl bluejay_core::definition::ArgumentsDefinition for ArgumentsDefinition {
|
7
|
+
type ArgumentDefinition = InputValueDefinition;
|
8
|
+
}
|
@@ -0,0 +1,61 @@
|
|
1
|
+
use super::{root, ExecutionError};
|
2
|
+
use crate::helpers::WrappedStruct;
|
3
|
+
use magnus::{function, Error, Module, Object, RArray, Value, method, rb_sys::AsRawValue};
|
4
|
+
|
5
|
+
#[derive(Clone, Debug, PartialEq)]
|
6
|
+
#[magnus::wrap(class = "Bluejay::CoercionError", mark)]
|
7
|
+
pub struct CoercionError {
|
8
|
+
message: String,
|
9
|
+
path: Vec<String>,
|
10
|
+
}
|
11
|
+
|
12
|
+
impl CoercionError {
|
13
|
+
pub fn new(message: String, path: Vec<String>) -> Self {
|
14
|
+
Self { message, path }
|
15
|
+
}
|
16
|
+
|
17
|
+
pub fn message(&self) -> &str {
|
18
|
+
self.message.as_str()
|
19
|
+
}
|
20
|
+
|
21
|
+
pub fn path(&self) -> RArray {
|
22
|
+
RArray::from_iter(self.path.iter().map(|s| s.as_str()))
|
23
|
+
}
|
24
|
+
|
25
|
+
pub fn eql(&self, other: Value) -> bool {
|
26
|
+
if let Ok(other) = other.try_convert::<&Self>() {
|
27
|
+
self == other
|
28
|
+
} else {
|
29
|
+
false
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
fn inspect(rb_self: WrappedStruct<Self>) -> Result<String, Error> {
|
34
|
+
let rs_self = rb_self.get();
|
35
|
+
|
36
|
+
Ok(format!(
|
37
|
+
"#<Bluejay::CoercionError:0x{:016x} @message={:?} @path={:?}>",
|
38
|
+
rb_self.to_value().as_raw(),
|
39
|
+
rs_self.message,
|
40
|
+
rs_self.path,
|
41
|
+
))
|
42
|
+
}
|
43
|
+
}
|
44
|
+
|
45
|
+
impl Into<ExecutionError> for CoercionError {
|
46
|
+
fn into(self) -> ExecutionError {
|
47
|
+
ExecutionError::new(self.message)
|
48
|
+
}
|
49
|
+
}
|
50
|
+
|
51
|
+
pub fn init() -> Result<(), Error> {
|
52
|
+
let class = root().define_class("CoercionError", Default::default())?;
|
53
|
+
|
54
|
+
class.define_singleton_method("new", function!(CoercionError::new, 2))?;
|
55
|
+
class.define_method("message", method!(CoercionError::message, 0))?;
|
56
|
+
class.define_method("path", method!(CoercionError::path, 0))?;
|
57
|
+
class.define_method("==", method!(CoercionError::eql, 1))?;
|
58
|
+
class.define_method("inspect", method!(CoercionError::inspect, 0))?;
|
59
|
+
|
60
|
+
Ok(())
|
61
|
+
}
|
@@ -0,0 +1,62 @@
|
|
1
|
+
use magnus::{function, Error, Module, Object, Value, scan_args::get_kwargs, RHash, memoize, TypedData, DataTypeFunctions, RClass};
|
2
|
+
use super::{root, coerce_input::CoerceInput, coercion_error::CoercionError};
|
3
|
+
use crate::helpers::{HasDefinitionWrapper};
|
4
|
+
|
5
|
+
#[derive(Clone, Debug, TypedData)]
|
6
|
+
#[magnus(class = "Bluejay::CustomScalarTypeDefinition", mark)]
|
7
|
+
pub struct CustomScalarTypeDefinition {
|
8
|
+
name: String,
|
9
|
+
description: Option<String>,
|
10
|
+
}
|
11
|
+
|
12
|
+
// TODO: add ability to coerce input and possibly coerce result
|
13
|
+
|
14
|
+
impl CustomScalarTypeDefinition {
|
15
|
+
fn new(kw: RHash) -> Result<Self, Error> {
|
16
|
+
let args = get_kwargs(kw, &["name", "description"], &[])?;
|
17
|
+
let (name, description): (String, Option<String>) = args.required;
|
18
|
+
let _: () = args.optional;
|
19
|
+
let _: () = args.splat;
|
20
|
+
Ok(Self { name, description })
|
21
|
+
}
|
22
|
+
|
23
|
+
pub fn name(&self) -> &str {
|
24
|
+
self.name.as_str()
|
25
|
+
}
|
26
|
+
|
27
|
+
pub fn description(&self) -> Option<&str> {
|
28
|
+
self.description.as_ref().map(String::as_str)
|
29
|
+
}
|
30
|
+
}
|
31
|
+
|
32
|
+
impl DataTypeFunctions for CustomScalarTypeDefinition {}
|
33
|
+
|
34
|
+
impl HasDefinitionWrapper for CustomScalarTypeDefinition {
|
35
|
+
fn wrapping_class() -> RClass {
|
36
|
+
*memoize!(RClass: root().define_class("CustomScalarType", Default::default()).unwrap())
|
37
|
+
}
|
38
|
+
}
|
39
|
+
|
40
|
+
impl CoerceInput for CustomScalarTypeDefinition {
|
41
|
+
fn coerce_input(&self, value: Value, _path: &[String]) -> Result<Result<Value, Vec<CoercionError>>, Error> {
|
42
|
+
Ok(Ok(value))
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
impl bluejay_core::definition::ScalarTypeDefinition for CustomScalarTypeDefinition {
|
47
|
+
fn description(&self) -> Option<&str> {
|
48
|
+
self.description.as_ref().map(|s| s.as_str())
|
49
|
+
}
|
50
|
+
|
51
|
+
fn name(&self) -> &str {
|
52
|
+
self.name.as_str()
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
56
|
+
pub fn init() -> Result<(), Error> {
|
57
|
+
let class = root().define_class("CustomScalarTypeDefinition", Default::default())?;
|
58
|
+
|
59
|
+
class.define_singleton_method("new", function!(CustomScalarTypeDefinition::new, 1))?;
|
60
|
+
|
61
|
+
Ok(())
|
62
|
+
}
|
@@ -0,0 +1,107 @@
|
|
1
|
+
use magnus::{function, Error, Module, Object, scan_args::get_kwargs, RHash, Value, memoize, TypedData, RArray, DataTypeFunctions, RClass, gc};
|
2
|
+
use bluejay_core::AsIter;
|
3
|
+
use super::{root, enum_value_definitions::EnumValueDefinitions, coerce_input::CoerceInput, coercion_error::CoercionError};
|
4
|
+
use crate::helpers::{public_name, HasDefinitionWrapper};
|
5
|
+
use crate::execution::{FieldError, CoerceResult};
|
6
|
+
|
7
|
+
#[derive(Debug, TypedData)]
|
8
|
+
#[magnus(class = "Bluejay::EnumTypeDefinition", mark)]
|
9
|
+
pub struct EnumTypeDefinition {
|
10
|
+
name: String,
|
11
|
+
description: Option<String>,
|
12
|
+
enum_value_definitions: EnumValueDefinitions,
|
13
|
+
}
|
14
|
+
|
15
|
+
impl EnumTypeDefinition {
|
16
|
+
fn new(kw: RHash) -> Result<Self, Error> {
|
17
|
+
let args = get_kwargs(kw, &["name", "enum_value_definitions", "description"], &[])?;
|
18
|
+
let (name, enum_value_definitions, description): (String, RArray, Option<String>) = args.required;
|
19
|
+
let _: () = args.optional;
|
20
|
+
let _: () = args.splat;
|
21
|
+
let enum_value_definitions = EnumValueDefinitions::new(enum_value_definitions)?;
|
22
|
+
Ok(Self { name, description, enum_value_definitions })
|
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 enum_value_definitions(&self) -> &EnumValueDefinitions {
|
34
|
+
&self.enum_value_definitions
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
38
|
+
impl DataTypeFunctions for EnumTypeDefinition {
|
39
|
+
fn mark(&self) {
|
40
|
+
gc::mark(self.enum_value_definitions);
|
41
|
+
}
|
42
|
+
}
|
43
|
+
|
44
|
+
impl CoerceInput for EnumTypeDefinition {
|
45
|
+
fn coerce_input(&self, value: Value, path: &[String]) -> Result<Result<Value, Vec<CoercionError>>, Error> {
|
46
|
+
let s: Result<String, _> = value.try_convert();
|
47
|
+
match s {
|
48
|
+
Ok(s) => {
|
49
|
+
// TODO: don't use const_get
|
50
|
+
if self.enum_value_definitions.iter().any(|evd| evd.name() == s.as_str()) {
|
51
|
+
Ok(Ok(value))
|
52
|
+
} else {
|
53
|
+
Ok(Err(vec![CoercionError::new(
|
54
|
+
format!("No member `{}` on {}", s.as_str(), self.name.as_str()),
|
55
|
+
path.to_owned(),
|
56
|
+
)]))
|
57
|
+
}
|
58
|
+
},
|
59
|
+
Err(_) => {
|
60
|
+
Ok(Err(vec![CoercionError::new(
|
61
|
+
format!("No implicit conversion of {} to {}", public_name(value), self.name.as_str()),
|
62
|
+
path.to_owned(),
|
63
|
+
)]))
|
64
|
+
}
|
65
|
+
}
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
69
|
+
impl HasDefinitionWrapper for EnumTypeDefinition {
|
70
|
+
fn wrapping_class() -> RClass {
|
71
|
+
*memoize!(RClass: root().define_class("EnumType", Default::default()).unwrap())
|
72
|
+
}
|
73
|
+
}
|
74
|
+
|
75
|
+
impl bluejay_core::definition::EnumTypeDefinition for EnumTypeDefinition {
|
76
|
+
type EnumValueDefinitions = EnumValueDefinitions;
|
77
|
+
|
78
|
+
fn description(&self) -> Option<&str> {
|
79
|
+
self.description.as_ref().map(String::as_str)
|
80
|
+
}
|
81
|
+
|
82
|
+
fn name(&self) -> &str {
|
83
|
+
self.name.as_str()
|
84
|
+
}
|
85
|
+
|
86
|
+
fn enum_value_definitions(&self) -> &Self::EnumValueDefinitions {
|
87
|
+
&self.enum_value_definitions
|
88
|
+
}
|
89
|
+
}
|
90
|
+
|
91
|
+
impl CoerceResult for EnumTypeDefinition {
|
92
|
+
fn coerce_result(&self, value: Value) -> Result<Value, FieldError> {
|
93
|
+
if value.try_convert().ok().map(|value: String| self.enum_value_definitions.iter().any(|evd| evd.name() == value.as_str())).unwrap_or(false) {
|
94
|
+
Ok(value)
|
95
|
+
} else {
|
96
|
+
Err(FieldError::CannotCoerceResultToEnumType)
|
97
|
+
}
|
98
|
+
}
|
99
|
+
}
|
100
|
+
|
101
|
+
pub fn init() -> Result<(), Error> {
|
102
|
+
let class = root().define_class("EnumTypeDefinition", Default::default())?;
|
103
|
+
|
104
|
+
class.define_singleton_method("new", function!(EnumTypeDefinition::new, 1))?;
|
105
|
+
|
106
|
+
Ok(())
|
107
|
+
}
|
@@ -0,0 +1,58 @@
|
|
1
|
+
use super::root;
|
2
|
+
use crate::helpers::WrappedStruct;
|
3
|
+
use magnus::{function, Error, Module, Object, scan_args::get_kwargs, RHash, TypedData, DataTypeFunctions, method};
|
4
|
+
|
5
|
+
#[derive(Clone, Debug, TypedData)]
|
6
|
+
#[magnus(class = "Bluejay::EnumValueDefinition", mark)]
|
7
|
+
pub struct EnumValueDefinition {
|
8
|
+
name: String,
|
9
|
+
description: Option<String>,
|
10
|
+
}
|
11
|
+
|
12
|
+
impl EnumValueDefinition {
|
13
|
+
pub fn new(kw: RHash) -> Result<Self, Error> {
|
14
|
+
let args = get_kwargs(kw, &["name"], &["description"])?;
|
15
|
+
let (name,): (String,) = args.required;
|
16
|
+
let (description,): (Option<String>,) = args.optional;
|
17
|
+
let _: () = args.splat;
|
18
|
+
Ok(Self { name, description })
|
19
|
+
}
|
20
|
+
|
21
|
+
pub fn name(&self) -> &str {
|
22
|
+
self.name.as_str()
|
23
|
+
}
|
24
|
+
}
|
25
|
+
|
26
|
+
impl DataTypeFunctions for EnumValueDefinition {
|
27
|
+
fn mark(&self) {
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
31
|
+
impl bluejay_core::definition::EnumValueDefinition for EnumValueDefinition {
|
32
|
+
fn description(&self) -> Option<&str> {
|
33
|
+
self.description.as_ref().map(String::as_str)
|
34
|
+
}
|
35
|
+
|
36
|
+
fn name(&self) -> &str {
|
37
|
+
self.name.as_str()
|
38
|
+
}
|
39
|
+
}
|
40
|
+
|
41
|
+
impl bluejay_core::definition::EnumValueDefinition for WrappedStruct<EnumValueDefinition> {
|
42
|
+
fn description(&self) -> Option<&str> {
|
43
|
+
self.get().description()
|
44
|
+
}
|
45
|
+
|
46
|
+
fn name(&self) -> &str {
|
47
|
+
self.get().name()
|
48
|
+
}
|
49
|
+
}
|
50
|
+
|
51
|
+
pub fn init() -> Result<(), Error> {
|
52
|
+
let class = root().define_class("EnumValueDefinition", Default::default())?;
|
53
|
+
|
54
|
+
class.define_singleton_method("new", function!(EnumValueDefinition::new, 1))?;
|
55
|
+
class.define_method("name", method!(EnumValueDefinition::name, 0))?;
|
56
|
+
|
57
|
+
Ok(())
|
58
|
+
}
|
@@ -0,0 +1,8 @@
|
|
1
|
+
use super::{enum_value_definition::EnumValueDefinition};
|
2
|
+
use crate::helpers::{WrappedStruct, TypedFrozenRArray};
|
3
|
+
|
4
|
+
pub type EnumValueDefinitions = TypedFrozenRArray<WrappedStruct<EnumValueDefinition>>;
|
5
|
+
|
6
|
+
impl bluejay_core::definition::EnumValueDefinitions for EnumValueDefinitions {
|
7
|
+
type EnumValueDefinition = EnumValueDefinition;
|
8
|
+
}
|
@@ -0,0 +1,48 @@
|
|
1
|
+
use super::root;
|
2
|
+
use crate::helpers::WrappedStruct;
|
3
|
+
use magnus::{function, Error, Module, Object, Value, method, rb_sys::AsRawValue};
|
4
|
+
|
5
|
+
#[derive(Clone, Debug, PartialEq)]
|
6
|
+
#[magnus::wrap(class = "Bluejay::ExecutionError", mark)]
|
7
|
+
pub struct ExecutionError {
|
8
|
+
message: String,
|
9
|
+
}
|
10
|
+
|
11
|
+
impl ExecutionError {
|
12
|
+
pub fn new(message: String) -> Self {
|
13
|
+
Self { message }
|
14
|
+
}
|
15
|
+
|
16
|
+
pub fn message(&self) -> &str {
|
17
|
+
self.message.as_str()
|
18
|
+
}
|
19
|
+
|
20
|
+
pub fn eql(&self, other: Value) -> bool {
|
21
|
+
if let Ok(other) = other.try_convert::<&Self>() {
|
22
|
+
self == other
|
23
|
+
} else {
|
24
|
+
false
|
25
|
+
}
|
26
|
+
}
|
27
|
+
|
28
|
+
fn inspect(rb_self: WrappedStruct<Self>) -> Result<String, Error> {
|
29
|
+
let rs_self = rb_self.get();
|
30
|
+
|
31
|
+
Ok(format!(
|
32
|
+
"#<Bluejay::ExecutionError:0x{:016x} @message={:?}>",
|
33
|
+
rb_self.to_value().as_raw(),
|
34
|
+
rs_self.message,
|
35
|
+
))
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
pub fn init() -> Result<(), Error> {
|
40
|
+
let class = root().define_class("ExecutionError", Default::default())?;
|
41
|
+
|
42
|
+
class.define_singleton_method("new", function!(ExecutionError::new, 1))?;
|
43
|
+
class.define_method("message", method!(ExecutionError::message, 0))?;
|
44
|
+
class.define_method("==", method!(ExecutionError::eql, 1))?;
|
45
|
+
class.define_method("inspect", method!(ExecutionError::inspect, 0))?;
|
46
|
+
|
47
|
+
Ok(())
|
48
|
+
}
|
@@ -0,0 +1,40 @@
|
|
1
|
+
use super::root;
|
2
|
+
use super::ExecutionError;
|
3
|
+
use crate::helpers::{WrappedStruct};
|
4
|
+
use magnus::{gc, Error, Module, RArray, Value, TypedData, DataTypeFunctions, method};
|
5
|
+
|
6
|
+
#[derive(Clone, Debug, TypedData)]
|
7
|
+
#[magnus(class = "Bluejay::ExecutionResult", mark)]
|
8
|
+
pub struct ExecutionResult {
|
9
|
+
value: Value,
|
10
|
+
errors: Vec<WrappedStruct<ExecutionError>>,
|
11
|
+
}
|
12
|
+
|
13
|
+
impl ExecutionResult {
|
14
|
+
pub fn new(value: Value, errors: Vec<WrappedStruct<ExecutionError>>) -> Self {
|
15
|
+
Self { value, errors }
|
16
|
+
}
|
17
|
+
|
18
|
+
fn value(&self) -> Value {
|
19
|
+
self.value
|
20
|
+
}
|
21
|
+
|
22
|
+
fn errors(&self) -> RArray {
|
23
|
+
RArray::from_iter(self.errors.iter().map(|err| *err))
|
24
|
+
}
|
25
|
+
}
|
26
|
+
|
27
|
+
impl DataTypeFunctions for ExecutionResult {
|
28
|
+
fn mark(&self) {
|
29
|
+
gc::mark(&self.value);
|
30
|
+
self.errors.iter().for_each(WrappedStruct::mark);
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
pub fn init() -> Result<(), Error> {
|
35
|
+
let class = root().define_class("ExecutionResult", Default::default())?;
|
36
|
+
class.define_method("value", method!(ExecutionResult::value, 0))?;
|
37
|
+
class.define_method("errors", method!(ExecutionResult::errors, 0))?;
|
38
|
+
|
39
|
+
Ok(())
|
40
|
+
}
|