diff --git a/terraform-provider-example/src/main.rs b/terraform-provider-example/src/main.rs index 8ad0fce..451b33d 100644 --- a/terraform-provider-example/src/main.rs +++ b/terraform-provider-example/src/main.rs @@ -3,8 +3,7 @@ use std::collections::HashMap; use terustform::{ datasource::{self, DataSource}, provider::Provider, - values::Value, - AttrPath, DResult, StringValue, ValueModel, + AttrPath, DResult, StringValue, Value, ValueModel, }; #[tokio::main] diff --git a/terustform/src/base.rs b/terustform/src/diag.rs similarity index 50% rename from terustform/src/base.rs rename to terustform/src/diag.rs index 2beb34d..d4a74aa 100644 --- a/terustform/src/base.rs +++ b/terustform/src/diag.rs @@ -1,5 +1,3 @@ -use crate::values::{Value, ValueKind}; - #[derive(Debug, Default)] pub struct Diagnostics { pub(crate) diags: Vec, @@ -14,6 +12,18 @@ pub struct Diagnostic { pub type DResult = Result; +// TODO: this could probably be a clever 0-alloc &-based linked list! + +#[derive(Debug, Clone, Default)] +pub struct AttrPath(pub(crate) Vec); + +#[derive(Debug, Clone)] +pub enum AttrPathSegment { + AttributeName(String), + ElementKeyString(String), + ElementKeyInt(i64), +} + impl Diagnostic { pub fn error_string(msg: impl Into) -> Self { Diagnostic { @@ -33,6 +43,20 @@ impl Diagnostics { } } +impl AttrPath { + pub fn root() -> Self { + Self::default() + } + pub fn attr(name: impl Into) -> Self { + Self(vec![AttrPathSegment::AttributeName(name.into())]) + } + pub fn append_attribute_name(&self, name: String) -> Self { + let mut p = self.clone(); + p.0.push(AttrPathSegment::AttributeName(name)); + p + } +} + impl From for Diagnostic { fn from(value: E) -> Self { Self::error_string(format!("{:?}", value)) @@ -49,93 +73,3 @@ impl From for Diagnostics { Self { diags: vec![value] } } } - -// TODO: this could probably be a clever 0-alloc &-based linked list! - -#[derive(Debug, Clone, Default)] -pub struct AttrPath(pub(crate) Vec); - -#[derive(Debug, Clone)] -pub enum AttrPathSegment { - AttributeName(String), - ElementKeyString(String), - ElementKeyInt(i64), -} - -impl AttrPath { - pub fn root() -> Self { - Self::default() - } - pub fn attr(name: impl Into) -> Self { - Self(vec![AttrPathSegment::AttributeName(name.into())]) - } - pub fn append_attribute_name(&self, name: String) -> Self { - let mut p = self.clone(); - p.0.push(AttrPathSegment::AttributeName(name)); - p - } -} - -pub type StringValue = BaseValue; -pub type I64Value = BaseValue; - -#[derive(Debug)] -pub enum BaseValue { - Unknown, - Null, - Known(T), -} - -impl BaseValue { - fn map(self, f: impl FnOnce(T) -> U) -> BaseValue { - self.try_map(|v| Ok(f(v))).unwrap() - } - - fn try_map(self, f: impl FnOnce(T) -> DResult) -> DResult> { - Ok(match self { - Self::Unknown => BaseValue::Unknown, - Self::Null => BaseValue::Null, - Self::Known(v) => BaseValue::Known(f(v)?), - }) - } - - pub fn expect_known(&self, path: AttrPath) -> DResult<&T> { - match self { - BaseValue::Null => Err(Diagnostic::error_string("expected value, found null value") - .with_path(path) - .into()), - BaseValue::Unknown => Err(Diagnostic::error_string( - "expected known value, found unknown value", - ) - .with_path(path) - .into()), - BaseValue::Known(v) => Ok(v), - } - } -} - -pub trait ValueModel: Sized { - fn from_value(v: Value, path: &AttrPath) -> DResult; - - fn to_value(self) -> Value; -} - -impl ValueModel for StringValue { - fn from_value(v: Value, path: &AttrPath) -> DResult { - v.try_map(|v| -> DResult { - match v { - ValueKind::String(s) => Ok(s), - _ => Err(Diagnostic::error_string(format!( - "expected string, found {}", - v.diagnostic_type_str() - )) - .with_path(path.clone()) - .into()), - } - }) - } - - fn to_value(self) -> Value { - self.map(ValueKind::String) - } -} diff --git a/terustform/src/lib.rs b/terustform/src/lib.rs index 78fb4d7..0650511 100644 --- a/terustform/src/lib.rs +++ b/terustform/src/lib.rs @@ -1,11 +1,13 @@ -mod base; +mod diag; +mod server; +mod values; + pub mod datasource; pub mod provider; -mod server; -pub mod values; -pub use base::*; +pub use diag::*; pub use terustform_macros::Model; +pub use values::*; use provider::Provider; @@ -24,9 +26,9 @@ pub async fn start(provider: &dyn Provider) -> eyre::Result<()> { /// Private, only for use for with the derive macro. #[doc(hidden)] pub mod __derive_private { - pub use crate::values::{Value, ValueKind}; pub use crate::{ - AttrPath, AttrPathSegment, BaseValue, DResult, Diagnostic, Diagnostics, ValueModel, + AttrPath, AttrPathSegment, BaseValue, DResult, Diagnostic, Diagnostics, Value, ValueKind, + ValueModel, }; pub use {Clone, Option::Some, Result::Err, ToOwned}; diff --git a/terustform/src/values.rs b/terustform/src/values.rs index 56769ba..63171d8 100644 --- a/terustform/src/values.rs +++ b/terustform/src/values.rs @@ -6,7 +6,7 @@ use std::{ io::{self, Read}, }; -use crate::{BaseValue, DResult, Diagnostic}; +use crate::{AttrPath, DResult, Diagnostic}; #[derive(Debug)] pub enum Type { @@ -108,6 +108,70 @@ impl ValueKind { } } +pub type StringValue = BaseValue; +pub type I64Value = BaseValue; + +#[derive(Debug)] +pub enum BaseValue { + Unknown, + Null, + Known(T), +} + +impl BaseValue { + fn map(self, f: impl FnOnce(T) -> U) -> BaseValue { + self.try_map(|v| Ok(f(v))).unwrap() + } + + fn try_map(self, f: impl FnOnce(T) -> DResult) -> DResult> { + Ok(match self { + Self::Unknown => BaseValue::Unknown, + Self::Null => BaseValue::Null, + Self::Known(v) => BaseValue::Known(f(v)?), + }) + } + + pub fn expect_known(&self, path: AttrPath) -> DResult<&T> { + match self { + BaseValue::Null => Err(Diagnostic::error_string("expected value, found null value") + .with_path(path) + .into()), + BaseValue::Unknown => Err(Diagnostic::error_string( + "expected known value, found unknown value", + ) + .with_path(path) + .into()), + BaseValue::Known(v) => Ok(v), + } + } +} + +pub trait ValueModel: Sized { + fn from_value(v: Value, path: &AttrPath) -> DResult; + + fn to_value(self) -> Value; +} + +impl ValueModel for StringValue { + fn from_value(v: Value, path: &AttrPath) -> DResult { + v.try_map(|v| -> DResult { + match v { + ValueKind::String(s) => Ok(s), + _ => Err(Diagnostic::error_string(format!( + "expected string, found {}", + v.diagnostic_type_str() + )) + .with_path(path.clone()) + .into()), + } + }) + } + + fn to_value(self) -> Value { + self.map(ValueKind::String) + } +} + // marshal msg pack // tftypes/value.go:MarshalMsgPack