1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
use bitflags::bitflags;
use nom::{IResult, Parser, combinator::map};
use crate::{
data_type::Int32,
error::{Error, error_position},
};
bitflags! {
/// 2.2.1.1 `MessageFlags`
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct MessageFlags: i32 {
/// The record contains no arguments.
/// It is in the Arg category.
const NO_ARGS = 0x00000001;
/// The Arguments Array is in the Args field of the Method record.
/// It is in the Arg category.
const ARGS_INLINE = 0x00000002;
/// Each argument is an item in a separate Call Array record.
/// It is in the Arg category.
const ARGS_IS_ARRAY = 0x00000004;
/// The Arguments Array is an item in a separate Call Array record.
/// It is in the Arg category.
const ARGS_IN_ARRAY = 0x00000008;
/// The record does not contain a Call Context value.
/// It is in the Context category.
const NO_CONTEXT = 0x00000010;
/// Call Context contains only a Logical Call ID value and is in
/// the CallContext field of the Method record.
/// It is in the Context category.
const CONTEXT_INLINE = 0x00000020;
/// CallContext values are contained in an array that is contained in the Call Array record.
/// It is in the Context category.
const CONTEXT_IN_ARRAY = 0x00000040;
/// The Method Signature is contained in the Call Array record.
/// It is in the Signature category.
const METHOD_SIGNATURE_IN_ARRAY = 0x00000080;
/// Message Properties is contained in the Call Array record.
/// It is in the Property category.
const PROPERTIES_IN_ARRAY = 0x00000100;
/// The Return Value is a Null object.
/// It is in the Return category.
const NO_RETURN_VALUE = 0x00000200;
/// The method has no Return Value.
/// It is in the Return category.
const RETURN_VALUE_VOID = 0x00000400;
/// The Return Value is in the ReturnValue field of the MethodReturnCallArray record.
/// It is in the Return category.
const RETURN_VALUE_INLINE = 0x00000800;
/// The Return Value is contained in the MethodReturnCallArray record.
/// It is in the Return category.
const RETURN_VALUE_IN_ARRAY = 0x00001000;
/// An Exception is contained in the MethodReturnCallArray record.
/// It is in the Exception category.
const EXCEPTION_IN_ARRAY = 0x00002000;
/// The Remote Method is generic and the actual Remoting Types
/// for the Generic Arguments are contained in the Call Array.
/// It is in the Generic category.
const GENERIC_METHOD = 0x00008000;
}
}
impl MessageFlags {
pub fn parse(input: &[u8]) -> IResult<&[u8], Self, Error<'_>> {
let err_input = input;
let (input, flags) = map(Int32::parse, |n| Self::from_bits_retain(n.0))
.parse(input)
.map_err(|err| err.map(|err| error_position!(err.input, ExpectedMessageFlags)))?;
let args_flags =
flags.intersection(Self::NO_ARGS.union(Self::ARGS_INLINE).union(Self::ARGS_IS_ARRAY).union(Self::ARGS_IN_ARRAY));
let context_flags = flags.intersection(Self::NO_CONTEXT.union(Self::CONTEXT_INLINE).union(Self::CONTEXT_IN_ARRAY));
let return_flags = flags.intersection(
Self::NO_RETURN_VALUE
.union(Self::RETURN_VALUE_VOID)
.union(Self::RETURN_VALUE_IN_ARRAY)
.union(Self::RETURN_VALUE_IN_ARRAY),
);
let signature_flags = flags.intersection(Self::METHOD_SIGNATURE_IN_ARRAY);
let exception_flags = flags.intersection(Self::EXCEPTION_IN_ARRAY);
// For each flags category given in the preceding table (Arg, Context, Signature, Return, Exception,
// Property, and Generic), the value MUST NOT have more than one flag from the Category set.
if args_flags.bits().count_ones() > 1
|| context_flags.bits().count_ones() > 1
|| return_flags.bits().count_ones() > 1
{
return Err(nom::Err::Failure(error_position!(err_input, InvalidMessageFlags)))
}
// The Args and Exception flag categories are exclusive: if a flag from the Args category is set, the
// value MUST NOT have any flag from the Exception category set, and vice versa.
if !args_flags.is_empty() && !exception_flags.is_empty() {
return Err(nom::Err::Failure(error_position!(err_input, InvalidMessageFlags)))
}
// The Return and Exception flag categories are exclusive: if a flag from the Return category is set,
// the value MUST NOT have any flag from the Exception category set, and vice versa.
if !return_flags.is_empty() && !exception_flags.is_empty() {
return Err(nom::Err::Failure(error_position!(err_input, InvalidMessageFlags)))
}
// The Return and Signature categories are exclusive: if a flag from the Return category is set, the
// value MUST NOT have any flag from the Signature category set, and vice versa.
if !return_flags.is_empty() && !signature_flags.is_empty() {
return Err(nom::Err::Failure(error_position!(err_input, InvalidMessageFlags)))
}
// The Exception and Signature categories are exclusive: if a flag from the Signature category is set,
// the value MUST NOT have any flag from the Exception category set, and vice versa.
if !exception_flags.is_empty() && !signature_flags.is_empty() {
return Err(nom::Err::Failure(error_position!(err_input, InvalidMessageFlags)))
}
Ok((input, flags))
}
}