use std::rc::Rc;
use crate::model::*;
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq)]
pub enum CallbackArgument {
Basic(BasicType),
String(StringType),
Iterator(AbstractIteratorHandle),
Class(ClassDeclarationHandle),
Struct(UniversalOr<CallbackArgStructField>),
}
impl From<BasicType> for CallbackArgument {
fn from(x: BasicType) -> Self {
Self::Basic(x)
}
}
impl From<Primitive> for CallbackArgument {
fn from(x: Primitive) -> Self {
Self::Basic(x.into())
}
}
impl From<Handle<Enum<Unvalidated>>> for CallbackArgument {
fn from(x: Handle<Enum<Unvalidated>>) -> Self {
Self::Basic(BasicType::Enum(x))
}
}
impl From<DurationType> for CallbackArgument {
fn from(x: DurationType) -> Self {
CallbackArgument::Basic(BasicType::Duration(x))
}
}
impl From<AbstractIteratorHandle> for CallbackArgument {
fn from(x: AbstractIteratorHandle) -> Self {
Self::Iterator(x)
}
}
impl From<UniversalStructHandle> for CallbackArgument {
fn from(x: UniversalStructHandle) -> Self {
Self::Struct(UniversalOr::Universal(x))
}
}
impl From<CallbackArgStructHandle> for CallbackArgument {
fn from(x: CallbackArgStructHandle) -> Self {
Self::Struct(x.into())
}
}
impl From<StringType> for CallbackArgument {
fn from(x: StringType) -> Self {
Self::String(x)
}
}
impl From<ClassDeclarationHandle> for CallbackArgument {
fn from(x: ClassDeclarationHandle) -> Self {
Self::Class(x)
}
}
#[derive(Debug, Clone)]
pub struct EnumValue {
pub(crate) handle: EnumHandle,
pub(crate) variant: EnumVariant<Unvalidated>,
}
impl EnumValue {
pub(crate) fn new(handle: EnumHandle, variant: &'static str) -> BindResult<Self> {
let variant = handle.validate_contains_variant_name(variant)?.clone();
Ok(Self { handle, variant })
}
}
#[derive(Debug, Clone)]
pub struct ZeroParameterStructInitializer {
pub(crate) handle: UniversalStructHandle,
pub(crate) initializer: Handle<Initializer<Unvalidated>>,
}
impl ZeroParameterStructInitializer {
fn try_create(handle: UniversalStructHandle, name: &'static str) -> BindResult<Self> {
let initializer = match handle.initializers.iter().find(|x| x.name == name) {
None => {
return Err(BindingErrorVariant::InitializerDoesNotExist {
name,
struct_name: handle.declaration.name().clone(),
}
.into())
}
Some(x) => x.clone(),
};
if initializer.values.len() != handle.fields.len() {
return Err(BindingErrorVariant::InitializerNotParameterless {
name,
struct_name: handle.declaration.name().clone(),
}
.into());
}
Ok(Self {
handle,
initializer,
})
}
}
impl UniversalStructHandle {
pub fn zero_parameter_initializer(
&self,
name: &'static str,
) -> BindResult<ZeroParameterStructInitializer> {
ZeroParameterStructInitializer::try_create(self.clone(), name)
}
}
#[non_exhaustive]
#[derive(Debug, Clone)]
pub enum BasicValue {
Primitive(PrimitiveValue),
Duration(DurationValue),
Enum(EnumValue),
}
impl BasicValue {
pub(crate) fn get_basic_type(&self) -> BasicType {
match self {
BasicValue::Primitive(x) => {
let pv: PrimitiveValue = *x;
let x: Primitive = pv.into();
BasicType::Primitive(x)
}
BasicValue::Duration(x) => {
let dv: DurationValue = *x;
let dt: DurationType = dv.into();
BasicType::Duration(dt)
}
BasicValue::Enum(x) => BasicType::Enum(x.handle.clone()),
}
}
}
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum CallbackReturnValue {
Basic(BasicType),
Struct(UniversalStructHandle),
}
#[non_exhaustive]
#[derive(Debug, Clone)]
pub enum DefaultCallbackReturnValue {
Void,
Basic(BasicValue),
InitializedStruct(ZeroParameterStructInitializer),
}
impl DefaultCallbackReturnValue {
pub(crate) fn get_callback_return_value(&self) -> Option<CallbackReturnValue> {
match self {
DefaultCallbackReturnValue::Void => None,
DefaultCallbackReturnValue::Basic(x) => {
Some(CallbackReturnValue::Basic(x.get_basic_type()))
}
DefaultCallbackReturnValue::InitializedStruct(x) => {
Some(CallbackReturnValue::Struct(x.handle.clone()))
}
}
}
}
impl From<ZeroParameterStructInitializer> for DefaultCallbackReturnValue {
fn from(x: ZeroParameterStructInitializer) -> Self {
DefaultCallbackReturnValue::InitializedStruct(x)
}
}
impl From<PrimitiveValue> for DefaultCallbackReturnValue {
fn from(x: PrimitiveValue) -> Self {
DefaultCallbackReturnValue::Basic(BasicValue::Primitive(x))
}
}
impl From<DurationValue> for DefaultCallbackReturnValue {
fn from(x: DurationValue) -> Self {
DefaultCallbackReturnValue::Basic(BasicValue::Duration(x))
}
}
impl From<EnumValue> for DefaultCallbackReturnValue {
fn from(x: EnumValue) -> Self {
DefaultCallbackReturnValue::Basic(BasicValue::Enum(x))
}
}
impl From<Primitive> for CallbackReturnValue {
fn from(x: Primitive) -> Self {
Self::Basic(x.into())
}
}
impl From<BasicType> for CallbackReturnValue {
fn from(x: BasicType) -> Self {
CallbackReturnValue::Basic(x)
}
}
impl From<UniversalStructHandle> for CallbackReturnValue {
fn from(x: UniversalStructHandle) -> Self {
CallbackReturnValue::Struct(x)
}
}
impl From<DurationType> for CallbackReturnValue {
fn from(x: DurationType) -> Self {
BasicType::Duration(x).into()
}
}
impl From<Handle<Enum<Unvalidated>>> for CallbackReturnValue {
fn from(x: Handle<Enum<Unvalidated>>) -> Self {
Self::Basic(BasicType::Enum(x))
}
}
pub type CallbackReturnType<T> = ReturnType<CallbackReturnValue, T>;
#[non_exhaustive]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum FunctionalTransform {
Yes,
No,
}
impl FunctionalTransform {
pub fn enabled(&self) -> bool {
match self {
FunctionalTransform::Yes => true,
FunctionalTransform::No => false,
}
}
}
#[derive(Debug)]
pub(crate) struct CallbackFunction<D>
where
D: DocReference,
{
pub(crate) name: Name,
pub(crate) functional_transform: FunctionalTransform,
pub(crate) return_type: OptionalReturnType<CallbackReturnValue, D>,
pub(crate) default_implementation: Option<DefaultCallbackReturnValue>,
pub(crate) arguments: Vec<Arg<CallbackArgument, D>>,
pub(crate) doc: Doc<D>,
}
impl CallbackFunction<Unvalidated> {
pub(crate) fn validate(&self, lib: &LibraryFields) -> BindResult<CallbackFunction<Validated>> {
let arguments: BindResult<Vec<Arg<CallbackArgument, Validated>>> =
self.arguments.iter().map(|x| x.validate(lib)).collect();
let argument_names: Vec<Name> = self.arguments.iter().map(|x| x.name.clone()).collect();
Ok(CallbackFunction {
name: self.name.clone(),
functional_transform: self.functional_transform,
return_type: self.return_type.validate(&self.name, lib)?,
default_implementation: self.default_implementation.clone(),
arguments: arguments?,
doc: self
.doc
.validate_with_args(&self.name, lib, Some(&argument_names))?,
})
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub(crate) enum InterfaceCategory {
Synchronous,
Asynchronous,
Future,
}
#[derive(Debug, Clone)]
pub(crate) enum InterfaceType<D>
where
D: DocReference,
{
Synchronous(Handle<Interface<D>>),
Asynchronous(Handle<Interface<D>>),
Future(FutureInterface<D>),
}
impl InterfaceType<Unvalidated> {
pub(crate) fn validate(&self, lib: &LibraryFields) -> BindResult<InterfaceType<Validated>> {
match self {
InterfaceType::Synchronous(x) => Ok(InterfaceType::Synchronous(x.validate(lib)?)),
InterfaceType::Asynchronous(x) => Ok(InterfaceType::Asynchronous(x.validate(lib)?)),
InterfaceType::Future(x) => Ok(InterfaceType::Future(x.validate(lib)?)),
}
}
}
impl<D> InterfaceType<D>
where
D: DocReference,
{
pub(crate) fn name(&self) -> &Name {
match self {
InterfaceType::Synchronous(x) => &x.name,
InterfaceType::Asynchronous(x) => &x.name,
InterfaceType::Future(x) => &x.interface.name,
}
}
pub(crate) fn mode(&self) -> InterfaceCategory {
match self {
InterfaceType::Synchronous(_) => InterfaceCategory::Synchronous,
InterfaceType::Asynchronous(_) => InterfaceCategory::Asynchronous,
InterfaceType::Future(_) => InterfaceCategory::Future,
}
}
pub(crate) fn doc(&self) -> &Doc<D> {
match self {
InterfaceType::Synchronous(x) => &x.doc,
InterfaceType::Asynchronous(x) => &x.doc,
InterfaceType::Future(x) => &x.interface.doc,
}
}
pub(crate) fn untyped(&self) -> &Handle<Interface<D>> {
match self {
InterfaceType::Synchronous(x) => x,
InterfaceType::Asynchronous(x) => x,
InterfaceType::Future(x) => &x.interface,
}
}
}
#[derive(Debug)]
pub struct Interface<D>
where
D: DocReference,
{
pub(crate) name: Name,
pub(crate) mode: InterfaceCategory,
pub(crate) callbacks: Vec<CallbackFunction<D>>,
pub(crate) doc: Doc<D>,
pub(crate) settings: Rc<LibrarySettings>,
}
impl Interface<Unvalidated> {
pub(crate) fn validate(&self, lib: &LibraryFields) -> BindResult<Handle<Interface<Validated>>> {
let callbacks: BindResult<Vec<CallbackFunction<Validated>>> =
self.callbacks.iter().map(|x| x.validate(lib)).collect();
Ok(Handle::new(Interface {
name: self.name.clone(),
mode: self.mode,
callbacks: callbacks?,
doc: self.doc.validate(&self.name, lib)?,
settings: self.settings.clone(),
}))
}
}
impl<D> Interface<D>
where
D: DocReference,
{
pub(crate) fn get_functional_callback(&self) -> Option<&CallbackFunction<D>> {
match self.callbacks.len() {
1 => self.callbacks.get(0),
_ => None,
}
}
pub(crate) fn is_functional(&self) -> bool {
self.get_functional_callback().is_some()
}
pub(crate) fn find_callback<S: AsRef<str>>(&self, name: S) -> Option<&CallbackFunction<D>> {
self.callbacks
.iter()
.find(|callback| callback.name.as_ref() == name.as_ref())
}
}
pub type InterfaceHandle = Handle<Interface<Unvalidated>>;
#[derive(Debug, Clone)]
pub struct AsynchronousInterface {
pub(crate) inner: InterfaceHandle,
}
#[derive(Debug, Clone)]
pub struct SynchronousInterface {
pub(crate) inner: InterfaceHandle,
}
#[derive(Debug, Clone)]
pub struct FutureInterface<D>
where
D: DocReference,
{
pub(crate) value_type: CallbackArgument,
pub(crate) value_type_doc: DocString<D>,
pub(crate) error_type: ErrorType<D>,
pub(crate) interface: Handle<Interface<D>>,
}
impl FutureInterface<Unvalidated> {
pub(crate) fn new(
value_type: CallbackArgument,
error_type: ErrorType<Unvalidated>,
interface: Handle<Interface<Unvalidated>>,
value_type_doc: DocString<Unvalidated>,
) -> Self {
Self {
value_type,
error_type,
value_type_doc,
interface,
}
}
pub(crate) fn validate(&self, lib: &LibraryFields) -> BindResult<FutureInterface<Validated>> {
Ok(FutureInterface {
value_type: self.value_type.clone(),
error_type: self.error_type.validate(lib)?,
value_type_doc: self.value_type_doc.validate(&self.interface.name, lib)?,
interface: self.interface.validate(lib)?,
})
}
}
pub type FutureInterfaceHandle = FutureInterface<Unvalidated>;