Variant
Variant 是 OPC UA 的通用值容器, 覆盖 OPC UA 全部内置数据类型. SDK 用它在 Rust 与
native 之间传值.
配套
- 包装值 + 时间戳 + 状态请看 DataValue.
- 标准节点常量请看 well_known_nodes.
公共方法
| 类别 | 属性 | 类型 | 访问 | 说明 |
|---|---|---|---|---|
| 类型 | data_type() | BuiltinType | R | 内置类型 |
| 构造 | Variant::new() | Variant | R | 空 Variant (Null), owns=true |
Variant::default() | Variant | R | 同 new() |
创建
use darra_opcua::Variant;
// 空 Variant (Null)
let v = Variant::new();
let v = Variant::default(); // 同上
Variant::new() 创建 owns=true 的实例, Drop 时自动释放底层 native 内存.
Setter (链式 builder)
每个 setter 返回 &mut Self:
let mut v = Variant::new();
v.set_bool(true);
v.set_byte(255);
v.set_sbyte(-1);
v.set_i16(42);
v.set_u16(42);
v.set_i32(42);
v.set_u32(42);
v.set_i64(42);
v.set_f32(3.14);
v.set_f64(3.14);
v.set_string("hello");
v.set_datetime(std::time::SystemTime::now());
Getter (返回 Option)
类型不匹配时返回 None, 不 panic:
let b: Option<bool> = v.try_get_bool();
let i: Option<i32> = v.try_get_i32();
let u: Option<u32> = v.try_get_u32();
let n: Option<i64> = v.try_get_i64();
let f: Option<f64> = v.try_get_f64();
let s: Option<String> = v.try_get_string();
let t: Option<SystemTime> = v.try_get_datetime();
let ft: Option<i64> = v.try_get_filetime(); // 原始 100ns ticks
兼容旧名 (与 0.5 之前版本对齐):
v.as_bool();
v.as_i32() / v.as_u32() / v.as_i64() / v.as_f64();
v.as_string() / v.as_datetime() / v.as_filetime();
数据类型查询
use darra_opcua::BuiltinType;
let t: BuiltinType = v.data_type();
match t {
BuiltinType::Boolean => { /* ... */ }
BuiltinType::Int32 => { /* ... */ }
BuiltinType::Double => { /* ... */ }
BuiltinType::String => { /* ... */ }
BuiltinType::DateTime => { /* ... */ }
BuiltinType::Null => { /* null */ }
_ => { /* 其他 */ }
}
Display / Debug
println!("{}", v); // 走 to_display_string()
println!("{:?}", v); // "Variant(Double=3.14)"
let s = v.to_display_string();
BuiltinType 完整清单
pub enum BuiltinType {
Null = 0, Boolean, SByte, Byte,
Int16, UInt16, Int32, UInt32, Int64, UInt64,
Float, Double, String, DateTime, Guid,
ByteString, XmlElement,
NodeId, ExpandedNodeId, StatusCode,
QualifiedName, LocalizedText, ExtensionObject,
DataValue, Variant, DiagnosticInfo,
}
数字 0..25.
内存所有权 (Drop)
Variant 包装 native handle, 实现 Drop:
{
let mut v = Variant::new();
v.set_f64(42.0);
s.write("ns=2;s=X", &v)?;
} // <- v Drop, native 内存自动释放
从 s.read / s.call 等返回的 Variant 是 owns=true, 同样自动释放, 不会泄漏.
订阅回调里通过 wrap_borrowed 拿到的 Variant 是 owns=false, 不释放底层 (C 层 Publish
线程管生命周期, 回调返回后失效).
StatusCode
StatusCode 是 newtype pub struct StatusCode(pub u32), 不是 enum (因为 OPC UA
允许任意未列出整数):
use darra_opcua::StatusCode;
let st = StatusCode(0);
assert_eq!(st, StatusCode::GOOD);
assert!(st.is_good());
// 关联常量 (节选, 完整见 enums.rs)
StatusCode::GOOD;
StatusCode::UNCERTAIN;
StatusCode::BAD;
StatusCode::BAD_NODE_ID_UNKNOWN;
StatusCode::BAD_NODE_ID_INVALID;
StatusCode::BAD_NOT_READABLE;
StatusCode::BAD_NOT_WRITABLE;
StatusCode::BAD_TYPE_MISMATCH;
StatusCode::BAD_USER_ACCESS_DENIED;
StatusCode::BAD_COMMUNICATION_ERROR;
StatusCode::BAD_TIMEOUT;
StatusCode::BAD_HISTORY_OPERATION_UNSUPPORTED;
StatusCode::BAD_NOT_SUPPORTED;
// Darra 私有
StatusCode::DARRA_INVALID_ARGUMENT;
StatusCode::DARRA_INVALID_HANDLE;
StatusCode::DARRA_OUT_OF_MEMORY;
StatusCode::DARRA_NOT_IMPLEMENTED;
// 实例方法
st.is_good(); // 高 2 位 = 00
st.is_uncertain(); // 高 2 位 = 01
st.is_bad(); // 高 2 位 = 1x
st.raw(); // 原始 u32
Display 输出 "0x00000000" 等十六进制格式.
ExtensionObject (复杂结构)
OPC UA Server 自定义 Struct DataType 通过 ExtensionObject 包装. 当前 SDK 提供基础 ExtensionObject 容器, 完整 schema 解析在后续版本.
跨线程
Variant 是 Send + Sync (内部 native 加锁), 可以在线程间传递. 但避免在订阅回调里
clone borrowed Variant 跨线程使用 — 用 to_display_string() 把数据"扁平化"再传出.