oss_vizier/model/study/
create.rs

1// Copyright 2022 Sebastien Soudan.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Study create request builder.
16
17use regex::Regex;
18
19use crate::vizier::{CreateStudyRequest, Study, StudySpec};
20
21/// Error returned by [RequestBuilder].
22#[derive(thiserror::Error, Debug)]
23pub enum Error {
24    /// The display_name is invalid.
25    #[error("display_name must match [a-z][a-z0-9_]*")]
26    InvalidDisplayName,
27    /// Display_name is missing
28    #[error("display_name is required")]
29    DisplayNameRequired,
30    /// Study_spec is missing
31    #[error("study_spec is required")]
32    StudySpecRequired,
33    /// Study_spec is missing or Display_name is missing
34    #[error("study_spec and display_name is required")]
35    StudySpecAndDisplayNameRequired,
36}
37
38/// [CreateStudyRequest] builder.
39pub struct RequestBuilder {
40    owner: String,
41    display_name: Option<String>,
42    study_spec: Option<StudySpec>,
43}
44
45impl RequestBuilder {
46    /// Create a new [RequestBuilder] for the given project and location.
47    pub fn new(owner: String) -> Self {
48        Self {
49            owner,
50            display_name: None,
51            study_spec: None,
52        }
53    }
54
55    /// Set the display name - required.
56    pub fn with_display_name(mut self, display_name: String) -> Self {
57        self.display_name = Some(display_name);
58        self
59    }
60
61    /// Set the study spec - required.
62    pub fn with_study_spec(mut self, study_spec: StudySpec) -> Self {
63        self.study_spec = Some(study_spec);
64        self
65    }
66
67    /// Builds the [CreateStudyRequest].
68    pub fn build(self) -> Result<CreateStudyRequest, Error> {
69        match (self.display_name, self.study_spec) {
70            (Some(display_name), Some(study_spec)) => {
71                let re = Regex::new(r"^[a-z][a-z\d_]*$").unwrap();
72                if !re.is_match(display_name.as_str()) {
73                    return Err(Error::InvalidDisplayName);
74                }
75
76                Ok(CreateStudyRequest {
77                    parent: format!("owners/{owner}", owner = &self.owner,),
78                    study: Some(Study {
79                        display_name,
80                        study_spec: Some(study_spec),
81                        ..Default::default()
82                    }),
83                })
84            }
85
86            (None, Some(_)) => Err(Error::DisplayNameRequired),
87            (Some(_), None) => Err(Error::StudySpecRequired),
88            (None, None) => Err(Error::StudySpecAndDisplayNameRequired),
89        }
90    }
91}