bridge_types/
lib.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
use std::borrow::Cow;
use std::fmt::Display;

/// A slosh [`Value`](../slvm/value/enum.Value.html) that can potentially be represented as a rust value.
/// Marker traits
pub trait BridgedType {}

/// An [`Option`] value that contains a [`BridgedType`] can be represented as a rust value.
impl<T> BridgedType for Option<T> where T: BridgedType {}

/// A [`Result`] value that contains a [`BridgedType`] can be represented as a rust value.
impl<T, U> BridgedType for Result<T, U> where T: BridgedType {}

/// A [`Vec`] that contains a [`BridgedType`] can be represented as a rust value.
impl<T> BridgedType for Vec<T> where T: BridgedType {}

/// Public type used by rust native -> slosh bridge macro to represent
/// arguments in slosh that correspond to variadic functions in rust
///
/// Type is useful so it is possible to write rust native functions
/// that appear in slosh as functions that can receive any number of arguments.
pub type VarArgs<T> = Vec<T>;

/// [`Value`]: /slvm/value/enum.Value.html
/// Type to hold anything in Slosh that can be represented as a [`String`].
///
/// Public type used by rust native -> slosh bridge macro to represent
/// arguments that can be loosely cast to strings. Unlike the [`String`]
/// and [`&str`] types, in slosh there are various types that can be
/// represented as strings. When the rust native function doesn't
/// require *strict* type checking on whether or not the [`Value`]`::String`
/// type is passed in use this function.
///
/// Can represent SlRefInto [`Value`] types:
/// - String
/// - CodePoint
/// - CharCluster
/// - CharClusterLong
/// - Symbol
/// - Keyword
/// - StringConst
///
/// Always does an allocation and returns a [`Value`]`::String` type.
pub type LooseString<'a> = Cow<'a, str>;

/// [`Value`]: /slvm/value/enum.Value.html
/// Type to hold Slosh's notion of a char.
///
/// In slosh a character can either be an actual char, e.g. a [`Value`]`::CodePoint`
/// or a [`Value`]`::CharCluster`/[`Value`]`::CharClusterLong` in which case it will
/// be stored in an &str.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SloshChar<'a> {
    Char(char),
    String(Cow<'a, str>),
}

impl Display for SloshChar<'_> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let str = match self {
            SloshChar::Char(c) => {
                format!("{}", c)
            }
            SloshChar::String(c) => c.to_string(),
        };
        write!(f, "{}", str)
    }
}

/// Used by sl_sh_fn macro to embed information at runtime about the parameters of
/// the rust native function, specifically whether it is a normal Type, or some
/// supported wrapped type, e.g. Optional.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum TypeHandle {
    Direct,
    Optional,
    VarArgs,
}

/// Used by sl_sh_fn macro to embed information at runtime about the parameters of
/// the rust native function, specifically whether it is going to pass the value (a move),
/// a reference, or mutable reference.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum PassingStyle {
    Value,
    Reference,
    MutReference,
}

/// Struct used by sl_sh_fn macro to embed information in an array at runtime about each of
/// the parameters of the rust native function.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Param {
    pub handle: TypeHandle,
    pub passing_style: PassingStyle,
}

//TODO PC ISSUE #8 use this! need common error messages but want a more comprehensive approach?
pub struct ErrorStrings {}

impl ErrorStrings {
    pub fn mismatched_type(
        fn_name: impl AsRef<str>,
        expected: impl AsRef<str>,
        got: impl AsRef<str>,
        additional: impl AsRef<str>,
    ) -> String {
        if additional.as_ref().is_empty() {
            format!(
                "{}: mismatched type input, expected value of type {}, got {}.",
                fn_name.as_ref(),
                expected.as_ref(),
                got.as_ref(),
            )
        } else {
            format!(
                "{}: mismatched type input, expected value of type {}, got {}. {}",
                fn_name.as_ref(),
                expected.as_ref(),
                got.as_ref(),
                additional.as_ref(),
            )
        }
    }

    pub fn fix_me_mismatched_type(expected: impl AsRef<str>, got: impl AsRef<str>) -> String {
        Self::mismatched_type("fixme", expected, got, "")
    }

    pub fn fix_me_mismatched_type_with_context(
        expected: impl AsRef<str>,
        got: impl AsRef<str>,
        additional: impl AsRef<str>,
    ) -> String {
        Self::mismatched_type("fixme", expected, got, additional)
    }
}