use alloc::string::{String, ToString};
use winnow::ModalResult as PResult;
use winnow::combinator::alt;
use winnow::prelude::*;
use winnow::token::any;
use crate::ast::Spanned;
use crate::lexer::Token;
use super::{Stream, parse_raw_string_lit};
pub(crate) fn parse_spanned_ident<'i, 'a>(input: &mut Stream<'i, 'a>) -> PResult<Spanned<&'a str>> {
let (t, span) = any
.verify(|(t, _)| {
!matches!(
t,
Token::RightArrow
| Token::LeftArrow
| Token::LBrace
| Token::RBrace
| Token::LParen
| Token::RParen
| Token::Comma
| Token::StringLit(_)
| Token::IpAddress(_)
| Token::MacAddress(_)
| Token::OidStr(_)
| Token::Number(_)
)
})
.parse_next(input)?;
let name = match t {
Token::Ident(s) => s,
Token::Ns => "ns",
Token::Us => "us",
Token::Ms => "ms",
Token::Sec => "s",
Token::Min => "m",
Token::Tcp => "TCP",
Token::Udp => "UDP",
Token::Snmp1 => "SNMP1",
Token::Snmp2 => "SNMP2",
Token::Snmp3 => "SNMP3",
Token::Syn => "SYN",
Token::Ack => "ACK",
Token::Fin => "FIN",
Token::Rst => "RST",
Token::Psh => "PSH",
Token::Urg => "URG",
Token::Ece => "ECE",
Token::Cwr => "CWR",
Token::SrcPort => "SRCPORT",
Token::DstPort => "DSTPORT",
Token::Seq => "SEQ",
Token::AckNum => "ACKNUM",
Token::Win => "WIN",
Token::Payload => "PAYLOAD",
Token::HexPayload => "HEXPAYLOAD",
Token::Wait => "WAIT",
Token::Vlan => "VLAN",
Token::Dscp => "DSCP",
Token::Ecn => "ECN",
Token::Ttl => "TTL",
Token::FlowLabel => "FLOWLABEL",
Token::Trap => "TRAP",
Token::Get => "GET",
Token::Set => "SET",
Token::Response => "RESPONSE",
Token::Inform => "INFORM",
Token::GetNext => "GETNEXT",
Token::GetBulk => "GETBULK",
Token::Community => "COMMUNITY",
Token::User => "USER",
Token::Oid => "OID",
Token::SysUpTime => "SYSUPTIME",
Token::VarBind => "VARBIND",
Token::NullVal => "NULLVAL",
Token::StringVal => "STRING",
Token::IntVal => "INT",
Token::TimeTicksVal => "TIMETICKS",
Token::IpVal => "IPVAL",
Token::OidVal => "OIDVAL",
Token::Counter32Val => "COUNTER32",
Token::Gauge32Val => "GAUGE32",
Token::Counter64Val => "COUNTER64",
Token::Enterprise => "ENTERPRISE",
Token::AgentIp => "AGENTIP",
Token::GenTrap => "GENTRAP",
Token::SpecTrap => "SPECTRAP",
Token::EngineId => "ENGINEID",
Token::EngineBoots => "ENGINEBOOTS",
Token::EngineTime => "ENGINETIME",
Token::ContextName => "CONTEXTNAME",
Token::Auth => "AUTH",
Token::Priv => "PRIV",
Token::Md5 => "MD5",
Token::Sha => "SHA",
Token::Sha256 => "SHA256",
Token::Sha384 => "SHA384",
Token::Sha512 => "SHA512",
Token::Des => "DES",
Token::Aes => "AES",
Token::NonRepeaters => "NONREPEATERS",
Token::MaxRepetitions => "MAXREPETITIONS",
Token::ReqId => "REQID",
Token::Pcp => "PCP",
Token::Dei => "DEI",
Token::Qinq => "QINQ",
Token::InnerVlan => "INNER_VLAN",
Token::Mpls => "MPLS",
Token::Exp => "EXP",
Token::Bos => "BOS",
Token::MplsTtl => "MPLS_TTL",
Token::SrcMac => "SRCMAC",
Token::DstMac => "DSTMAC",
Token::EtherType => "ETHERTYPE",
Token::IpId => "IPID",
Token::Df => "DF",
Token::Mf => "MF",
Token::FragOffset => "FRAGOFFSET",
Token::Transport => "TRANSPORT",
Token::Window => "WINDOW",
Token::Urgent => "URGENT",
Token::Mss => "MSS",
Token::Wscale => "WSCALE",
Token::SackPerm => "SACK_PERM",
Token::Tsval => "TSVAL",
Token::Tsecr => "TSECR",
Token::Vtag => "VTAG",
Token::Stream => "STREAM",
Token::Ssn => "SSN",
Token::Ppid => "PPID",
Token::Chunk => "CHUNK",
Token::Arp => "ARP",
Token::Lldp => "LLDP",
Token::Stp => "STP",
Token::Lacp => "LACP",
Token::Eapol => "EAPOL",
Token::Icmp => "ICMP",
Token::Ndp => "NDP",
Token::Igmp => "IGMP",
Token::Mld => "MLD",
Token::Gre => "GRE",
Token::Vxlan => "VXLAN",
Token::Geneve => "GENEVE",
Token::Ipsec => "IPSEC",
Token::Esp => "ESP",
Token::Ah => "AH",
Token::Ikev2 => "IKEV2",
Token::Wireguard => "WIREGUARD",
Token::Ospf => "OSPF",
Token::Bgp => "BGP",
Token::Rip => "RIP",
Token::Vrrp => "VRRP",
Token::Hsrp => "HSRP",
Token::Pim => "PIM",
Token::Bfd => "BFD",
Token::Openflow => "OPENFLOW",
Token::Sctp => "SCTP",
Token::Request => "REQUEST",
Token::Reply => "REPLY",
Token::Gratuitous => "GRATUITOUS",
Token::Garp => "GARP",
Token::Spa => "SPA",
Token::Tha => "THA",
Token::Tpa => "TPA",
Token::SenderMac => "SENDERMAC",
Token::TargetMac => "TARGETMAC",
Token::SenderIp => "SENDERIP",
Token::TargetIp => "TARGETIP",
Token::ChassisId => "CHASSIS_ID",
Token::PortId => "PORT_ID",
Token::SysName => "SYSNAME",
Token::SysDesc => "SYSDESC",
Token::RootId => "ROOT_ID",
Token::BridgeId => "BRIDGE_ID",
Token::Cost => "COST",
Token::MaxAge => "MAX_AGE",
Token::HelloTime => "HELLO_TIME",
Token::ForwardDelay => "FORWARD_DELAY",
Token::Rstp => "RSTP",
Token::Flags => "FLAGS",
Token::ActorSys => "ACTOR_SYS",
Token::ActorKey => "ACTOR_KEY",
Token::ActorPort => "ACTOR_PORT",
Token::PartnerSys => "PARTNER_SYS",
Token::PartnerKey => "PARTNER_KEY",
Token::PartnerPort => "PARTNER_PORT",
Token::ActorState => "ACTOR_STATE",
Token::PartnerState => "PARTNER_STATE",
Token::Version => "VERSION",
Token::Type => "TYPE",
Token::EapPacket => "EAP_PACKET",
Token::Start => "START",
Token::Logoff => "LOGOFF",
Token::Key => "KEY",
Token::EapCode => "EAP_CODE",
Token::EapId => "EAP_ID",
Token::EapMethod => "EAP_METHOD",
Token::Identity => "IDENTITY",
Token::Label => "LABEL",
Token::EchoRequest => "ECHO_REQUEST",
Token::EchoReply => "ECHO_REPLY",
Token::DestUnreach => "DEST_UNREACH",
Token::TimeExceeded => "TIME_EXCEEDED",
Token::Redirect => "REDIRECT",
Token::Code => "CODE",
Token::Id => "ID",
Token::Gateway => "GATEWAY",
Token::RouterSolicit => "ROUTER_SOLICIT",
Token::RouterAdvert => "ROUTER_ADVERT",
Token::NeighborSolicit => "NEIGHBOR_SOLICIT",
Token::NeighborAdvert => "NEIGHBOR_ADVERT",
Token::Target => "TARGET",
Token::Slla => "SLLA",
Token::Tlla => "TLLA",
Token::RouterLifetime => "ROUTER_LIFETIME",
Token::Query => "QUERY",
Token::Report => "REPORT",
Token::Leave => "LEAVE",
Token::Group => "GROUP",
Token::MaxResp => "MAX_RESP",
Token::V1 => "V1",
Token::V2 => "V2",
Token::V3 => "V3",
Token::Done => "DONE",
Token::MulticastAddr => "MULTICAST_ADDR",
Token::MaxRespDelay => "MAX_RESP_DELAY",
Token::GreKey => "GRE_KEY",
Token::GreSeq => "GRE_SEQ",
Token::GreProto => "GRE_PROTO",
Token::Checksum => "CHECKSUM",
Token::Vni => "VNI",
Token::Vnid => "VNID",
Token::OptClass => "OPT_CLASS",
Token::OptType => "OPT_TYPE",
Token::ProtocolType => "PROTOCOL_TYPE",
Token::Spi => "SPI",
Token::Iv => "IV",
Token::Icv => "ICV",
Token::NextHeader => "NEXT_HEADER",
Token::InitiatorSpi => "INITIATOR_SPI",
Token::ResponderSpi => "RESPONDER_SPI",
Token::Exchange => "EXCHANGE",
Token::SaInit => "SA_INIT",
Token::CreateChildSa => "CREATE_CHILD_SA",
Token::Informational => "INFORMATIONAL",
Token::MsgId => "MSGID",
Token::NextPayload => "NEXT_PAYLOAD",
Token::Initiation => "INITIATION",
Token::Cookie => "COOKIE",
Token::Data => "DATA",
Token::Sender => "SENDER",
Token::Receiver => "RECEIVER",
Token::Counter => "COUNTER",
Token::Hello => "HELLO",
Token::Dbd => "DBD",
Token::Lsr => "LSR",
Token::Lsu => "LSU",
Token::LsAck => "LSACK",
Token::RouterId => "ROUTER_ID",
Token::AreaId => "AREA_ID",
Token::HelloInterval => "HELLO_INTERVAL",
Token::DeadInterval => "DEAD_INTERVAL",
Token::Priority => "PRIORITY",
Token::Open => "OPEN",
Token::Update => "UPDATE",
Token::Notification => "NOTIFICATION",
Token::Keepalive => "KEEPALIVE",
Token::Asn => "ASN",
Token::HoldTime => "HOLDTIME",
Token::BgpId => "BGPID",
Token::Prefix => "PREFIX",
Token::Nlri => "NLRI",
Token::NextHop => "NEXTHOP",
Token::Metric => "METRIC",
Token::Tag => "TAG",
Token::Vrid => "VRID",
Token::AdvInt => "ADV_INT",
Token::Vip => "VIP",
Token::HelloTimeHsrp => "HELLOTIME",
Token::State => "STATE",
Token::JoinPrune => "JOIN_PRUNE",
Token::Register => "REGISTER",
Token::Source => "SOURCE",
Token::Rp => "RP",
Token::DrPriority => "DR_PRIORITY",
Token::Diag => "DIAG",
Token::MyDisc => "MY_DISC",
Token::YourDisc => "YOUR_DISC",
Token::MinTx => "MIN_TX",
Token::MinRx => "MIN_RX",
Token::Mult => "MULT",
Token::FeaturesReq => "FEATURES_REQ",
Token::FeaturesReply => "FEATURES_REPLY",
Token::PacketIn => "PACKET_IN",
Token::PacketOut => "PACKET_OUT",
Token::FlowMod => "FLOW_MOD",
Token::EchoReq => "ECHO_REQ",
Token::Xid => "XID",
Token::Dpid => "DPID",
Token::TableId => "TABLE_ID",
Token::Init => "INIT",
Token::InitAck => "INIT_ACK",
Token::Sack => "SACK",
Token::Heartbeat => "HEARTBEAT",
Token::HeartbeatAck => "HEARTBEAT_ACK",
Token::Abort => "ABORT",
Token::Shutdown => "SHUTDOWN",
Token::CookieEcho => "COOKIE_ECHO",
Token::CookieAck => "COOKIE_ACK",
Token::Tsn => "TSN",
Token::Dns => "DNS",
Token::Mdns => "MDNS",
Token::Dhcp => "DHCP",
Token::Ntp => "NTP",
Token::Ptp => "PTP",
Token::Radius => "RADIUS",
Token::Tacacs => "TACACS",
Token::Syslog => "SYSLOG",
Token::Netflow => "NETFLOW",
Token::Ipfix => "IPFIX",
Token::Sflow => "SFLOW",
Token::Tftp => "TFTP",
Token::Ftp => "FTP",
Token::Ssh => "SSH",
Token::Telnet => "TELNET",
Token::Http => "HTTP",
Token::Http2 => "HTTP2",
Token::Grpc => "GRPC",
Token::Websocket => "WEBSOCKET",
Token::Tls => "TLS",
Token::Quic => "QUIC",
Token::Stun => "STUN",
Token::Sip => "SIP",
Token::Rtp => "RTP",
Token::Rtsp => "RTSP",
Token::Smtp => "SMTP",
Token::Imap => "IMAP",
Token::Pop3 => "POP3",
Token::Kerberos => "KERBEROS",
Token::Ldap => "LDAP",
Token::Smb => "SMB",
Token::Nfs => "NFS",
Token::Redis => "REDIS",
Token::Memcached => "MEMCACHED",
Token::Mysql => "MYSQL",
Token::Postgres => "POSTGRES",
Token::Mqtt => "MQTT",
Token::Coap => "COAP",
Token::Amqp => "AMQP",
Token::Ssdp => "SSDP",
Token::Whois => "WHOIS",
Token::Modbus => "MODBUS",
Token::Bacnet => "BACNET",
Token::Dnp3 => "DNP3",
Token::S7comm => "S7COMM",
Token::Ethernetip => "ETHERNETIP",
Token::Opcua => "OPCUA",
Token::Txid => "TXID",
Token::Qname => "QNAME",
Token::Qtype => "QTYPE",
Token::Rdata => "RDATA",
Token::Rcode => "RCODE",
Token::AnsTtl => "ANS_TTL",
Token::Discover => "DISCOVER",
Token::Solicit => "SOLICIT",
Token::Offer => "OFFER",
Token::Advertise => "ADVERTISE",
Token::Release => "RELEASE",
Token::Ciaddr => "CIADDR",
Token::Yiaddr => "YIADDR",
Token::Siaddr => "SIADDR",
Token::Chaddr => "CHADDR",
Token::Hostname => "HOSTNAME",
Token::DnsServer => "DNS_SERVER",
Token::Router => "ROUTER",
Token::SubnetMask => "SUBNET_MASK",
Token::LeaseTime => "LEASE_TIME",
Token::Li => "LI",
Token::Vn => "VN",
Token::Mode => "MODE",
Token::Stratum => "STRATUM",
Token::Poll => "POLL",
Token::Precision => "PRECISION",
Token::RefId => "REFID",
Token::TxTimestamp => "TX_TIMESTAMP",
Token::MsgType => "MSG_TYPE",
Token::Sync => "SYNC",
Token::DelayReq => "DELAY_REQ",
Token::FollowUp => "FOLLOW_UP",
Token::DelayResp => "DELAY_RESP",
Token::Announce => "ANNOUNCE",
Token::Domain => "DOMAIN",
Token::SeqId => "SEQ_ID",
Token::ClockId => "CLOCK_ID",
Token::AccessRequest => "ACCESS_REQUEST",
Token::AccessAccept => "ACCESS_ACCEPT",
Token::AccessReject => "ACCESS_REJECT",
Token::AccessChallenge => "ACCESS_CHALLENGE",
Token::AccountingRequest => "ACCOUNTING_REQUEST",
Token::AccountingResponse => "ACCOUNTING_RESPONSE",
Token::NasIp => "NAS_IP",
Token::ServiceType => "SERVICE_TYPE",
Token::FramedIp => "FRAMED_IP",
Token::Authen => "AUTHEN",
Token::Author => "AUTHOR",
Token::Acct => "ACCT",
Token::SessionId => "SESSION_ID",
Token::Facility => "FACILITY",
Token::Severity => "SEVERITY",
Token::Pri => "PRI",
Token::App => "APP",
Token::Procid => "PROCID",
Token::Msg => "MSG",
Token::SrcIp => "SRCIP",
Token::DstIp => "DSTIP",
Token::Proto => "PROTO",
Token::Packets => "PACKETS",
Token::Octets => "OCTETS",
Token::DomainId => "DOMAIN_ID",
Token::AgentIpSflow => "AGENT_IP",
Token::SubAgentId => "SUB_AGENT_ID",
Token::Uptime => "UPTIME",
Token::Samples => "SAMPLES",
Token::Rrq => "RRQ",
Token::Wrq => "WRQ",
Token::Filename => "FILENAME",
Token::Block => "BLOCK",
Token::ErrCode => "ERRCODE",
Token::ErrMsg => "ERRMSG",
Token::Cmd => "CMD",
Token::Arg => "ARG",
Token::Banner => "BANNER",
Token::KexInit => "KEXINIT",
Token::NewKeys => "NEWKEYS",
Token::MsgCode => "MSG_CODE",
Token::Will => "WILL",
Token::Wont => "WONT",
Token::DoCmd => "DO",
Token::Dont => "DONT",
Token::Option => "OPTION",
Token::Post => "POST",
Token::Put => "PUT",
Token::Delete => "DELETE",
Token::Head => "HEAD",
Token::Options => "OPTIONS",
Token::Patch => "PATCH",
Token::Uri => "URI",
Token::HostHdr => "HOST_HDR",
Token::UserAgent => "USER_AGENT",
Token::ContentType => "CONTENT_TYPE",
Token::Status => "STATUS",
Token::Reason => "REASON",
Token::Header => "HEADER",
Token::Body => "BODY",
Token::Preface => "PREFACE",
Token::Settings => "SETTINGS",
Token::Headers => "HEADERS",
Token::WindowUpdate => "WINDOW_UPDATE",
Token::Ping => "PING",
Token::Goaway => "GOAWAY",
Token::StreamId => "STREAM_ID",
Token::Service => "SERVICE",
Token::Method => "METHOD",
Token::GrpcStatus => "GRPC_STATUS",
Token::Opcode => "OPCODE",
Token::Text => "TEXT",
Token::Binary => "BINARY",
Token::Pong => "PONG",
Token::Close => "CLOSE",
Token::FinBit => "FIN_BIT",
Token::MaskKey => "MASK_KEY",
Token::ClientHello => "CLIENT_HELLO",
Token::ServerHello => "SERVER_HELLO",
Token::Certificate => "CERTIFICATE",
Token::Finished => "FINISHED",
Token::AppData => "APP_DATA",
Token::Alert => "ALERT",
Token::RecordVersion => "RECORD_VERSION",
Token::HandshakeVersion => "HANDSHAKE_VERSION",
Token::Sni => "SNI",
Token::Ciphersuite => "CIPHERSUITE",
Token::Alpn => "ALPN",
Token::Initial => "INITIAL",
Token::ZeroRtt => "ZERO_RTT",
Token::Handshake => "HANDSHAKE",
Token::Retry => "RETRY",
Token::Short => "SHORT",
Token::Dcid => "DCID",
Token::Scid => "SCID",
Token::Token => "TOKEN",
Token::PktNum => "PKT_NUM",
Token::BindingRequest => "BINDING_REQUEST",
Token::BindingResponse => "BINDING_RESPONSE",
Token::BindingError => "BINDING_ERROR",
Token::XorMappedAddr => "XOR_MAPPED_ADDR",
Token::Software => "SOFTWARE",
Token::Invite => "INVITE",
Token::Bye => "BYE",
Token::Cancel => "CANCEL",
Token::From => "FROM",
Token::To => "TO",
Token::CallId => "CALL_ID",
Token::Cseq => "CSEQ",
Token::Via => "VIA",
Token::Contact => "CONTACT",
Token::Pt => "PT",
Token::Timestamp => "TIMESTAMP",
Token::Ssrc => "SSRC",
Token::Marker => "MARKER",
Token::Describe => "DESCRIBE",
Token::Setup => "SETUP",
Token::Play => "PLAY",
Token::Teardown => "TEARDOWN",
Token::TransportHdr => "TRANSPORT_HDR",
Token::Session => "SESSION",
Token::Ehlo => "EHLO",
Token::Helo => "HELO",
Token::MailFrom => "MAIL_FROM",
Token::RcptTo => "RCPT_TO",
Token::Quit => "QUIT",
Token::Param => "PARAM",
Token::Ok => "OK",
Token::Err => "ERR",
Token::AsReq => "AS_REQ",
Token::AsRep => "AS_REP",
Token::TgsReq => "TGS_REQ",
Token::TgsRep => "TGS_REP",
Token::KrbError => "KRB_ERROR",
Token::Realm => "REALM",
Token::Cname => "CNAME",
Token::Sname => "SNAME",
Token::Etype => "ETYPE",
Token::BindReq => "BIND_REQ",
Token::BindRes => "BIND_RES",
Token::SearchReq => "SEARCH_REQ",
Token::SearchEntry => "SEARCH_ENTRY",
Token::SearchDone => "SEARCH_DONE",
Token::UnbindReq => "UNBIND_REQ",
Token::BaseDn => "BASE_DN",
Token::Filter => "FILTER",
Token::ResultCode => "RESULT_CODE",
Token::Command => "COMMAND",
Token::Negotiate => "NEGOTIATE",
Token::SessionSetup => "SESSION_SETUP",
Token::TreeConnect => "TREE_CONNECT",
Token::Create => "CREATE",
Token::TreeDisconnect => "TREE_DISCONNECT",
Token::TreeId => "TREE_ID",
Token::Share => "SHARE",
Token::Vers => "VERS",
Token::Proc => "PROC",
Token::Path => "PATH",
Token::Compound => "COMPOUND",
Token::Args => "ARGS",
Token::ReplyType => "REPLY_TYPE",
Token::Value => "VALUE",
Token::Exptime => "EXPTIME",
Token::Opaque => "OPAQUE",
Token::Cas => "CAS",
Token::Greeting => "GREETING",
Token::Login => "LOGIN",
Token::Sql => "SQL",
Token::Eof => "EOF",
Token::ServerVersion => "SERVER_VERSION",
Token::Db => "DB",
Token::Startup => "STARTUP",
Token::ReadyForQuery => "READY_FOR_QUERY",
Token::CommandComplete => "COMMAND_COMPLETE",
Token::ErrorResponse => "ERROR_RESPONSE",
Token::AuthOk => "AUTH_OK",
Token::Connect => "CONNECT",
Token::Connack => "CONNACK",
Token::Publish => "PUBLISH",
Token::Puback => "PUBACK",
Token::Subscribe => "SUBSCRIBE",
Token::Suback => "SUBACK",
Token::Pingreq => "PINGREQ",
Token::Pingresp => "PINGRESP",
Token::Disconnect => "DISCONNECT",
Token::ClientId => "CLIENT_ID",
Token::Topic => "TOPIC",
Token::Qos => "QOS",
Token::Retain => "RETAIN",
Token::PktId => "PKT_ID",
Token::ReturnCode => "RETURN_CODE",
Token::Con => "CON",
Token::Non => "NON",
Token::Changed => "CHANGED",
Token::Created => "CREATED",
Token::NotFound => "NOT_FOUND",
Token::UriPath => "URI_PATH",
Token::ContentFormat => "CONTENT_FORMAT",
Token::ProtocolHeader => "PROTOCOL_HEADER",
Token::ConnectionStart => "CONNECTION_START",
Token::ChannelOpen => "CHANNEL_OPEN",
Token::BasicPublish => "BASIC_PUBLISH",
Token::BasicDeliver => "BASIC_DELIVER",
Token::Channel => "CHANNEL",
Token::RoutingKey => "ROUTING_KEY",
Token::Msearch => "MSEARCH",
Token::Notify => "NOTIFY",
Token::Man => "MAN",
Token::Mx => "MX",
Token::St => "ST",
Token::Nt => "NT",
Token::Nts => "NTS",
Token::Usn => "USN",
Token::Location => "LOCATION",
Token::Registrar => "REGISTRAR",
Token::ProtoId => "PROTO_ID",
Token::UnitId => "UNITID",
Token::Func => "FUNC",
Token::ReadCoils => "READ_COILS",
Token::ReadDiscreteInputs => "READ_DISCRETE_INPUTS",
Token::ReadHoldingRegisters => "READ_HOLDING_REGISTERS",
Token::ReadInputRegisters => "READ_INPUT_REGISTERS",
Token::WriteSingleCoil => "WRITE_SINGLE_COIL",
Token::WriteSingleRegister => "WRITE_SINGLE_REGISTER",
Token::WriteMultipleRegisters => "WRITE_MULTIPLE_REGISTERS",
Token::Addr => "ADDR",
Token::Count => "COUNT",
Token::IsResponse => "IS_RESPONSE",
Token::WhoIs => "WHO_IS",
Token::IAm => "I_AM",
Token::ReadProperty => "READ_PROPERTY",
Token::WriteProperty => "WRITE_PROPERTY",
Token::InvokeId => "INVOKE_ID",
Token::ObjectType => "OBJECT_TYPE",
Token::ObjectInstance => "OBJECT_INSTANCE",
Token::PropertyId => "PROPERTY_ID",
Token::Confirm => "CONFIRM",
Token::Select => "SELECT",
Token::Operate => "OPERATE",
Token::DirectOperate => "DIRECT_OPERATE",
Token::UnsolicitedResponse => "UNSOLICITED_RESPONSE",
Token::Variation => "VARIATION",
Token::Crc => "CRC",
Token::Src => "SRC",
Token::Dst => "DST",
Token::Rosctr => "ROSCTR",
Token::PduRef => "PDU_REF",
Token::SetupComm => "SETUP_COMM",
Token::ReadVar => "READ_VAR",
Token::WriteVar => "WRITE_VAR",
Token::PlcControl => "PLC_CONTROL",
Token::Area => "AREA",
Token::DbNum => "DB_NUM",
Token::Offset => "OFFSET",
Token::ListServices => "LIST_SERVICES",
Token::ListIdentity => "LIST_IDENTITY",
Token::ListInterfaces => "LIST_INTERFACES",
Token::RegisterSession => "REGISTER_SESSION",
Token::UnregisterSession => "UNREGISTER_SESSION",
Token::SendRrData => "SEND_RR_DATA",
Token::SendUnitData => "SEND_UNIT_DATA",
Token::SessionHandle => "SESSION_HANDLE",
Token::ContextVal => "CONTEXT",
Token::CipService => "CIP_SERVICE",
Token::CipClass => "CIP_CLASS",
Token::CipInstance => "CIP_INSTANCE",
Token::CipAttr => "CIP_ATTR",
Token::ChunkType => "CHUNK_TYPE",
Token::SecureChannelId => "SECURE_CHANNEL_ID",
Token::TokenId => "TOKEN_ID",
Token::SeqNum => "SEQ_NUM",
Token::EndpointUrl => "ENDPOINT_URL",
Token::NodeId => "NODE_ID",
_ => unreachable!(),
};
Ok(Spanned::new(name, (span.start, span.end - span.start)))
}
pub(crate) fn parse_ident<'i, 'a>(input: &mut Stream<'i, 'a>) -> PResult<&'a str> {
parse_spanned_ident.map(|s| s.node).parse_next(input)
}
pub(crate) fn parse_any_str<'i, 'a>(input: &mut Stream<'i, 'a>) -> PResult<&'a str> {
alt((
parse_raw_string_lit,
parse_ident,
any.verify_map(|(t, _)| match t {
Token::Number(s)
| Token::IpAddress(s)
| Token::MacAddress(s)
| Token::OidStr(s) => Some(s),
_ => None,
}),
))
.parse_next(input)
}
pub fn unescape_string(s: &str) -> Result<String, String> {
let mut out = String::with_capacity(s.len());
let mut chars = s.chars();
while let Some(c) = chars.next() {
if c == '\\' {
match chars.next() {
Some('r') => out.push('\r'),
Some('n') => out.push('\n'),
Some('t') => out.push('\t'),
Some('\\') => out.push('\\'),
Some('"') => out.push('"'),
Some('\'') => out.push('\''),
Some('x') => {
let h1 = chars
.next()
.ok_or_else(|| "Incomplete \\x escape sequence".to_string())?;
let h2 = chars
.next()
.ok_or_else(|| "Incomplete \\x escape sequence".to_string())?;
let mut hex_buf = [0u8; 2];
hex_buf[0] = h1 as u8;
hex_buf[1] = h2 as u8;
let hex_str = core::str::from_utf8(&hex_buf)
.map_err(|_| "Invalid ASCII hex digit in \\x".to_string())?;
let byte = u8::from_str_radix(hex_str, 16)
.map_err(|_| alloc::format!("Invalid hex byte in \\x: {}", hex_str))?;
out.push(byte as char);
}
Some('u') => {
let mut hex_buf = [0u8; 4];
for b in &mut hex_buf {
let ch = chars
.next()
.ok_or_else(|| "Incomplete \\u escape sequence".to_string())?;
*b = ch as u8;
}
let hex_str = core::str::from_utf8(&hex_buf)
.map_err(|_| "Invalid ASCII hex digit in \\u".to_string())?;
let code = u32::from_str_radix(hex_str, 16)
.map_err(|_| alloc::format!("Invalid unicode hex in \\u: {}", hex_str))?;
let ch = char::from_u32(code)
.ok_or_else(|| alloc::format!("Invalid unicode codepoint: {:x}", code))?;
out.push(ch);
}
Some(other) => out.push(other),
None => return Err("Dangling backslash at end of string".to_string()),
}
} else {
out.push(c);
}
}
Ok(out)
}