use crate::checker::types::TypeId;
use crate::diagnostics::DiagnosticMap;
use crate::state_accessors::StateAccessors;
pub const STREAMS_NAMESPACE: &str = "TypeSpec.Streams";
pub const STATE_STREAM_OF: &str = "TypeSpec.Streams.streamOf";
pub fn create_streams_library() -> DiagnosticMap {
DiagnosticMap::new()
}
typeid_decorator!(apply_stream_of, get_stream_of, STATE_STREAM_OF);
pub fn is_stream(state: &StateAccessors, target: TypeId) -> bool {
state.get_state(STATE_STREAM_OF, target).is_some()
}
pub const STREAMS_DECORATORS_TSP: &str = r#"
using TypeSpec.Reflection;
namespace TypeSpec.Streams;
/**
* Specify that a model represents a stream protocol type whose data is described
* by `Type`.
*
* @param type The type that models the underlying data of the stream.
*
* @example
*
* ```typespec
* model Message {
* id: string;
* text: string;
* }
*
* @streamOf(Message)
* model Response {
* @body body: string;
* }
* ```
*/
extern dec streamOf(target: Model, type: unknown);
"#;
pub const STREAMS_TYPES_TSP: &str = r#"
namespace TypeSpec.Streams;
/**
* Defines a model that represents a stream protocol type whose data is described
* by `Type`.
*
* This can be useful when the underlying data type is not relevant, or to serve as
* a base type for custom streams.
*
* @template Type The type of the stream's data.
*/
@doc("")
@streamOf(Type)
model Stream<Type> {}
"#;
pub const STREAMS_MAIN_TSP: &str = r#"
import "../dist/src/tsp-index.js";
import "./decorators.tsp";
import "./types.tsp";
"#;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_streams_namespace() {
assert_eq!(STREAMS_NAMESPACE, "TypeSpec.Streams");
}
#[test]
fn test_state_key() {
assert!(STATE_STREAM_OF.starts_with("TypeSpec.Streams"));
}
#[test]
fn test_create_streams_library() {
let lib = create_streams_library();
assert!(lib.is_empty(), "streams library has no diagnostics");
}
#[test]
fn test_decorators_tsp_not_empty() {
assert!(!STREAMS_DECORATORS_TSP.is_empty());
assert!(STREAMS_DECORATORS_TSP.contains("streamOf"));
}
#[test]
fn test_types_tsp_not_empty() {
assert!(!STREAMS_TYPES_TSP.is_empty());
assert!(STREAMS_TYPES_TSP.contains("Stream"));
}
#[test]
fn test_is_stream_and_get_stream_of() {
let mut state = StateAccessors::new();
assert!(!is_stream(&state, 1));
assert_eq!(get_stream_of(&state, 1), None);
apply_stream_of(&mut state, 1, 42);
assert!(is_stream(&state, 1));
assert_eq!(get_stream_of(&state, 1), Some(42));
assert!(!is_stream(&state, 2));
}
#[test]
fn test_apply_stream_of_overwrite() {
let mut state = StateAccessors::new();
apply_stream_of(&mut state, 1, 10);
assert_eq!(get_stream_of(&state, 1), Some(10));
apply_stream_of(&mut state, 1, 20);
assert_eq!(get_stream_of(&state, 1), Some(20));
}
}