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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
use chrono::{DateTime, Utc};
use ordered_float::NotNan;
use serde::{Deserialize, Serialize};
use std::str::FromStr;

use crate::{
    error::{Error, Result},
    ModelVersion,
};

use super::{
    comment::{Comment, CommentFilter, Entity, PredictedLabel, Uid as CommentUid},
    dataset::{FullName as DatasetFullName, Id as DatasetId},
    label_def::Name as LabelName,
};

#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, Hash)]
pub struct Name(pub String);

#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, Hash)]
pub struct Id(pub String);

#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, Hash)]
pub struct SequenceId(pub String);

#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, Hash)]
pub struct FullName {
    pub dataset: DatasetFullName,
    pub stream: Name,
}

impl FromStr for FullName {
    type Err = Error;

    fn from_str(string: &str) -> Result<Self> {
        let mut splits = string.split('/');
        match (splits.next(), splits.next(), splits.next(), splits.next()) {
            (Some(owner), Some(dataset), Some(stream_name), None) => Ok(FullName {
                dataset: DatasetFullName(format!("{owner}/{dataset}")),
                stream: Name(stream_name.to_owned()),
            }),
            _ => Err(Error::BadStreamName {
                identifier: string.into(),
            }),
        }
    }
}

#[derive(Debug, Clone, Serialize)]
pub(crate) struct PutStreamRequest<'request> {
    pub stream: &'request NewStream,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PutStreamResponse {
    pub stream: Stream,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct NewStream {
    pub name: Name,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub title: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub description: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub comment_filter: Option<CommentFilter>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub model: Option<StreamModel>,
}

impl NewStream {
    pub fn set_model_version(&mut self, model_version: &ModelVersion) {
        if let Some(model) = &mut self.model {
            model.version = model_version.clone()
        }
    }
}

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct StreamModel {
    pub version: ModelVersion,
    pub label_thresholds: Vec<StreamLabelThreshold>,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct StreamLabelThreshold {
    pub name: Vec<String>,
    pub threshold: NotNan<f64>,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Stream {
    pub id: Id,
    pub dataset_id: DatasetId,
    pub name: Name,
    pub title: String,
    pub description: String,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,

    #[serde(default)]
    pub comment_filter: CommentFilter,

    #[serde(rename = "label_threshold_filter")]
    pub label_filter: Option<LabelFilter>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub model: Option<StreamModel>,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct LabelFilter {
    pub label: LabelName,
    pub model_version: ModelVersion,
    pub threshold: NotNan<f64>,
}

impl FromStr for ModelVersion {
    type Err = Error;

    fn from_str(s: &str) -> Result<Self> {
        match s.parse::<u32>() {
            Ok(version) => Ok(ModelVersion(version)),
            Err(_) => Err(Error::BadStreamModelVersion {
                version: s.to_string(),
            }),
        }
    }
}

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Batch {
    pub results: Vec<StreamResult>,
    pub filtered: u32,
    pub sequence_id: SequenceId,
    pub is_end_sequence: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StreamResult {
    pub comment: Comment,
    pub sequence_id: SequenceId,
    pub labels: Option<Vec<PredictedLabel>>,
    pub entities: Option<Vec<Entity>>,
}

#[derive(Debug, Clone, Deserialize)]
pub(crate) struct GetStreamsResponse {
    pub streams: Vec<Stream>,
}

#[derive(Debug, Clone, Deserialize)]
pub(crate) struct GetStreamResponse {
    pub stream: Stream,
}

#[derive(Debug, Clone, Serialize)]
pub(crate) struct FetchRequest {
    pub size: u32,
}

#[derive(Debug, Clone, Serialize)]
pub(crate) struct AdvanceRequest {
    pub sequence_id: SequenceId,
}

#[derive(Debug, Clone, Serialize)]
pub(crate) struct ResetRequest {
    pub to_comment_created_at: DateTime<Utc>,
}

#[derive(Debug, Clone, Serialize)]
pub(crate) struct TagExceptionsRequest<'request> {
    pub exceptions: &'request [StreamException<'request>],
}

#[derive(Debug, Clone, Serialize)]
pub struct StreamException<'request> {
    pub metadata: StreamExceptionMetadata<'request>,
    pub uid: &'request CommentUid,
}

#[derive(Debug, Clone, Serialize)]
pub struct StreamExceptionMetadata<'request> {
    pub r#type: &'request String,
}