跳到主要内容

Variant

Variant 是 OPC UA 的通用值容器, 覆盖 OPC UA 全部内置数据类型. SDK 用它在 Rust 与 native 之间传值.

配套

公共方法

类别属性类型访问说明
类型data_type()BuiltinTypeR内置类型
构造Variant::new()VariantR空 Variant (Null), owns=true
Variant::default()VariantR同 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 解析在后续版本.

跨线程

VariantSend + Sync (内部 native 加锁), 可以在线程间传递. 但避免在订阅回调里 clone borrowed Variant 跨线程使用 — 用 to_display_string() 把数据"扁平化"再传出.

下一步