adding envs tagging/interpolation
This commit is contained in:
parent
eed9c34ebf
commit
b64c318a4a
@ -1,155 +1,155 @@
|
|||||||
package protos
|
package protos
|
||||||
|
|
||||||
var (
|
var (
|
||||||
RegisteredProtoHOPOPT0 := &protos.IPProto{Name:"HOPOPT", Description:"IPv6 Hop-by-Hop Option", Number:0x0, csvNum:"", Reference:"[RFC8200]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoHOPOPT0 *IPProto = &IPProto{Name:"HOPOPT", Description:"IPv6 Hop-by-Hop Option", Number:0x0, csvNum:"", Reference:"[RFC8200]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoICMP0 := &protos.IPProto{Name:"ICMP", Description:"Internet Control Message", Number:0x0, csvNum:"", Reference:"[RFC792]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoICMP0 = &IPProto{Name:"ICMP", Description:"Internet Control Message", Number:0x0, csvNum:"", Reference:"[RFC792]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoIGMP0 := &protos.IPProto{Name:"IGMP", Description:"Internet Group Management", Number:0x0, csvNum:"", Reference:"[RFC1112]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoIGMP0 = &IPProto{Name:"IGMP", Description:"Internet Group Management", Number:0x0, csvNum:"", Reference:"[RFC1112]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoGGP0 := &protos.IPProto{Name:"GGP", Description:"Gateway-to-Gateway", Number:0x0, csvNum:"", Reference:"[RFC823]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoGGP0 = &IPProto{Name:"GGP", Description:"Gateway-to-Gateway", Number:0x0, csvNum:"", Reference:"[RFC823]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoIPv40 := &protos.IPProto{Name:"IPv4", Description:"IPv4 encapsulation", Number:0x0, csvNum:"", Reference:"[RFC2003]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoIPv40 = &IPProto{Name:"IPv4", Description:"IPv4 encapsulation", Number:0x0, csvNum:"", Reference:"[RFC2003]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoST0 := &protos.IPProto{Name:"ST", Description:"Stream", Number:0x0, csvNum:"", Reference:"[RFC1190][RFC1819]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoST0 = &IPProto{Name:"ST", Description:"Stream", Number:0x0, csvNum:"", Reference:"[RFC1190][RFC1819]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoTCP0 := &protos.IPProto{Name:"TCP", Description:"Transmission Control", Number:0x0, csvNum:"", Reference:"[RFC793]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoTCP0 = &IPProto{Name:"TCP", Description:"Transmission Control", Number:0x0, csvNum:"", Reference:"[RFC793]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoCBT0 := &protos.IPProto{Name:"CBT", Description:"CBT", Number:0x0, csvNum:"", Reference:"[Tony_Ballardie]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoCBT0 = &IPProto{Name:"CBT", Description:"CBT", Number:0x0, csvNum:"", Reference:"[Tony_Ballardie]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoEGP0 := &protos.IPProto{Name:"EGP", Description:"Exterior Gateway Protocol", Number:0x0, csvNum:"", Reference:"[RFC888][David_Mills]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoEGP0 = &IPProto{Name:"EGP", Description:"Exterior Gateway Protocol", Number:0x0, csvNum:"", Reference:"[RFC888][David_Mills]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoIGP0 := &protos.IPProto{Name:"IGP", Description:"any private interior gateway \n(used by Cisco for their IGRP)", Number:0x0, csvNum:"", Reference:"[Internet_Assigned_Numbers_Authority]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoIGP0 = &IPProto{Name:"IGP", Description:"any private interior gateway \n(used by Cisco for their IGRP)", Number:0x0, csvNum:"", Reference:"[Internet_Assigned_Numbers_Authority]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoBBN-RCC-MON0 := &protos.IPProto{Name:"BBN-RCC-MON", Description:"BBN RCC Monitoring", Number:0x0, csvNum:"", Reference:"[Steve_Chipman]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoBBN_RCC_MON0 = &IPProto{Name:"BBN-RCC-MON", Description:"BBN RCC Monitoring", Number:0x0, csvNum:"", Reference:"[Steve_Chipman]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoNVP-II0 := &protos.IPProto{Name:"NVP-II", Description:"Network Voice Protocol", Number:0x0, csvNum:"", Reference:"[RFC741][Steve_Casner]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoNVP_II0 = &IPProto{Name:"NVP-II", Description:"Network Voice Protocol", Number:0x0, csvNum:"", Reference:"[RFC741][Steve_Casner]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoPUP0 := &protos.IPProto{Name:"PUP", Description:"PUP", Number:0x0, csvNum:"", Reference:"[Boggs, D., J. Shoch, E. Taft, and R. Metcalfe, \"PUP: An\nInternetwork Architecture\", XEROX Palo Alto Research Center,\nCSL-79-10, July 1979; also in IEEE Transactions on\nCommunication, Volume COM-28, Number 4, April 1980.][[XEROX]]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoPUP0 = &IPProto{Name:"PUP", Description:"PUP", Number:0x0, csvNum:"", Reference:"[Boggs, D., J. Shoch, E. Taft, and R. Metcalfe, \"PUP: An\nInternetwork Architecture\", XEROX Palo Alto Research Center,\nCSL-79-10, July 1979; also in IEEE Transactions on\nCommunication, Volume COM-28, Number 4, April 1980.][[XEROX]]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoARGUS (deprecated)0 := &protos.IPProto{Name:"ARGUS (deprecated)", Description:"ARGUS", Number:0x0, csvNum:"", Reference:"[Robert_W_Scheifler]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoARGUS = &IPProto{Name:"ARGUS (deprecated)", Description:"ARGUS", Number:0x0, csvNum:"", Reference:"[Robert_W_Scheifler]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoEMCON0 := &protos.IPProto{Name:"EMCON", Description:"EMCON", Number:0x0, csvNum:"", Reference:"[<mystery contact>]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoEMCON0 = &IPProto{Name:"EMCON", Description:"EMCON", Number:0x0, csvNum:"", Reference:"[<mystery contact>]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoXNET0 := &protos.IPProto{Name:"XNET", Description:"Cross Net Debugger", Number:0x0, csvNum:"", Reference:"[Haverty, J., \"XNET Formats for Internet Protocol Version 4\",\nIEN 158, October 1980.][Jack_Haverty]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoXNET0 = &IPProto{Name:"XNET", Description:"Cross Net Debugger", Number:0x0, csvNum:"", Reference:"[Haverty, J., \"XNET Formats for Internet Protocol Version 4\",\nIEN 158, October 1980.][Jack_Haverty]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoCHAOS0 := &protos.IPProto{Name:"CHAOS", Description:"Chaos", Number:0x0, csvNum:"", Reference:"[J_Noel_Chiappa]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoCHAOS0 = &IPProto{Name:"CHAOS", Description:"Chaos", Number:0x0, csvNum:"", Reference:"[J_Noel_Chiappa]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoUDP0 := &protos.IPProto{Name:"UDP", Description:"User Datagram", Number:0x0, csvNum:"", Reference:"[RFC768][Jon_Postel]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoUDP0 = &IPProto{Name:"UDP", Description:"User Datagram", Number:0x0, csvNum:"", Reference:"[RFC768][Jon_Postel]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoMUX0 := &protos.IPProto{Name:"MUX", Description:"Multiplexing", Number:0x0, csvNum:"", Reference:"[Cohen, D. and J. Postel, \"Multiplexing Protocol\", IEN 90,\nUSC/Information Sciences Institute, May 1979.][Jon_Postel]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoMUX0 = &IPProto{Name:"MUX", Description:"Multiplexing", Number:0x0, csvNum:"", Reference:"[Cohen, D. and J. Postel, \"Multiplexing Protocol\", IEN 90,\nUSC/Information Sciences Institute, May 1979.][Jon_Postel]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoDCN-MEAS0 := &protos.IPProto{Name:"DCN-MEAS", Description:"DCN Measurement Subsystems", Number:0x0, csvNum:"", Reference:"[David_Mills]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoDCN_MEAS0 = &IPProto{Name:"DCN-MEAS", Description:"DCN Measurement Subsystems", Number:0x0, csvNum:"", Reference:"[David_Mills]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoHMP0 := &protos.IPProto{Name:"HMP", Description:"Host Monitoring", Number:0x0, csvNum:"", Reference:"[RFC869][Bob_Hinden]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoHMP0 = &IPProto{Name:"HMP", Description:"Host Monitoring", Number:0x0, csvNum:"", Reference:"[RFC869][Bob_Hinden]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoPRM0 := &protos.IPProto{Name:"PRM", Description:"Packet Radio Measurement", Number:0x0, csvNum:"", Reference:"[Zaw_Sing_Su]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoPRM0 = &IPProto{Name:"PRM", Description:"Packet Radio Measurement", Number:0x0, csvNum:"", Reference:"[Zaw_Sing_Su]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoXNS-IDP0 := &protos.IPProto{Name:"XNS-IDP", Description:"XEROX NS IDP", Number:0x0, csvNum:"", Reference:"[\"The Ethernet, A Local Area Network: Data Link Layer and\nPhysical Layer Specification\", AA-K759B-TK, Digital\nEquipment Corporation, Maynard, MA. Also as: \"The\nEthernet - A Local Area Network\", Version 1.0, Digital\nEquipment Corporation, Intel Corporation, Xerox\nCorporation, September 1980. And: \"The Ethernet, A Local\nArea Network: Data Link Layer and Physical Layer\nSpecifications\", Digital, Intel and Xerox, November 1982.\nAnd: XEROX, \"The Ethernet, A Local Area Network: Data Link\nLayer and Physical Layer Specification\", X3T51/80-50,\nXerox Corporation, Stamford, CT., October 1980.][[XEROX]]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoXNS_IDP0 = &IPProto{Name:"XNS-IDP", Description:"XEROX NS IDP", Number:0x0, csvNum:"", Reference:"[\"The Ethernet, A Local Area Network: Data Link Layer and\nPhysical Layer Specification\", AA-K759B-TK, Digital\nEquipment Corporation, Maynard, MA. Also as: \"The\nEthernet - A Local Area Network\", Version 1.0, Digital\nEquipment Corporation, Intel Corporation, Xerox\nCorporation, September 1980. And: \"The Ethernet, A Local\nArea Network: Data Link Layer and Physical Layer\nSpecifications\", Digital, Intel and Xerox, November 1982.\nAnd: XEROX, \"The Ethernet, A Local Area Network: Data Link\nLayer and Physical Layer Specification\", X3T51/80-50,\nXerox Corporation, Stamford, CT., October 1980.][[XEROX]]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoTRUNK-10 := &protos.IPProto{Name:"TRUNK-1", Description:"Trunk-1", Number:0x0, csvNum:"", Reference:"[Barry_Boehm]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoTRUNK_10 = &IPProto{Name:"TRUNK-1", Description:"Trunk-1", Number:0x0, csvNum:"", Reference:"[Barry_Boehm]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoTRUNK-20 := &protos.IPProto{Name:"TRUNK-2", Description:"Trunk-2", Number:0x0, csvNum:"", Reference:"[Barry_Boehm]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoTRUNK_20 = &IPProto{Name:"TRUNK-2", Description:"Trunk-2", Number:0x0, csvNum:"", Reference:"[Barry_Boehm]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoLEAF-10 := &protos.IPProto{Name:"LEAF-1", Description:"Leaf-1", Number:0x0, csvNum:"", Reference:"[Barry_Boehm]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoLEAF_10 = &IPProto{Name:"LEAF-1", Description:"Leaf-1", Number:0x0, csvNum:"", Reference:"[Barry_Boehm]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoLEAF-20 := &protos.IPProto{Name:"LEAF-2", Description:"Leaf-2", Number:0x0, csvNum:"", Reference:"[Barry_Boehm]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoLEAF_20 = &IPProto{Name:"LEAF-2", Description:"Leaf-2", Number:0x0, csvNum:"", Reference:"[Barry_Boehm]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoRDP0 := &protos.IPProto{Name:"RDP", Description:"Reliable Data Protocol", Number:0x0, csvNum:"", Reference:"[RFC908][Bob_Hinden]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoRDP0 = &IPProto{Name:"RDP", Description:"Reliable Data Protocol", Number:0x0, csvNum:"", Reference:"[RFC908][Bob_Hinden]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoIRTP0 := &protos.IPProto{Name:"IRTP", Description:"Internet Reliable Transaction", Number:0x0, csvNum:"", Reference:"[RFC938][Trudy_Miller]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoIRTP0 = &IPProto{Name:"IRTP", Description:"Internet Reliable Transaction", Number:0x0, csvNum:"", Reference:"[RFC938][Trudy_Miller]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoISO-TP40 := &protos.IPProto{Name:"ISO-TP4", Description:"ISO Transport Protocol Class 4", Number:0x0, csvNum:"", Reference:"[RFC905][<mystery contact>]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoISO-TP40 = &IPProto{Name:"ISO-TP4", Description:"ISO Transport Protocol Class 4", Number:0x0, csvNum:"", Reference:"[RFC905][<mystery contact>]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoNETBLT0 := &protos.IPProto{Name:"NETBLT", Description:"Bulk Data Transfer Protocol", Number:0x0, csvNum:"", Reference:"[RFC969][David_Clark]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoNETBLT0 = &IPProto{Name:"NETBLT", Description:"Bulk Data Transfer Protocol", Number:0x0, csvNum:"", Reference:"[RFC969][David_Clark]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoMFE-NSP0 := &protos.IPProto{Name:"MFE-NSP", Description:"MFE Network Services Protocol", Number:0x0, csvNum:"", Reference:"[Shuttleworth, B., \"A Documentary of MFENet, a National\nComputer Network\", UCRL-52317, Lawrence Livermore Labs,\nLivermore, California, June 1977.][Barry_Howard]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoMFE-NSP0 = &IPProto{Name:"MFE-NSP", Description:"MFE Network Services Protocol", Number:0x0, csvNum:"", Reference:"[Shuttleworth, B., \"A Documentary of MFENet, a National\nComputer Network\", UCRL-52317, Lawrence Livermore Labs,\nLivermore, California, June 1977.][Barry_Howard]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoMERIT-INP0 := &protos.IPProto{Name:"MERIT-INP", Description:"MERIT Internodal Protocol", Number:0x0, csvNum:"", Reference:"[Hans_Werner_Braun]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoMERIT-INP0 = &IPProto{Name:"MERIT-INP", Description:"MERIT Internodal Protocol", Number:0x0, csvNum:"", Reference:"[Hans_Werner_Braun]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoDCCP0 := &protos.IPProto{Name:"DCCP", Description:"Datagram Congestion Control Protocol", Number:0x0, csvNum:"", Reference:"[RFC4340]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoDCCP0 = &IPProto{Name:"DCCP", Description:"Datagram Congestion Control Protocol", Number:0x0, csvNum:"", Reference:"[RFC4340]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProto3PC0 := &protos.IPProto{Name:"3PC", Description:"Third Party Connect Protocol", Number:0x0, csvNum:"", Reference:"[Stuart_A_Friedberg]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProto3PC0 = &IPProto{Name:"3PC", Description:"Third Party Connect Protocol", Number:0x0, csvNum:"", Reference:"[Stuart_A_Friedberg]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoIDPR0 := &protos.IPProto{Name:"IDPR", Description:"Inter-Domain Policy Routing Protocol", Number:0x0, csvNum:"", Reference:"[Martha_Steenstrup]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoIDPR0 = &IPProto{Name:"IDPR", Description:"Inter-Domain Policy Routing Protocol", Number:0x0, csvNum:"", Reference:"[Martha_Steenstrup]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoXTP0 := &protos.IPProto{Name:"XTP", Description:"XTP", Number:0x0, csvNum:"", Reference:"[Greg_Chesson]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoXTP0 = &IPProto{Name:"XTP", Description:"XTP", Number:0x0, csvNum:"", Reference:"[Greg_Chesson]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoDDP0 := &protos.IPProto{Name:"DDP", Description:"Datagram Delivery Protocol", Number:0x0, csvNum:"", Reference:"[Wesley_Craig]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoDDP0 = &IPProto{Name:"DDP", Description:"Datagram Delivery Protocol", Number:0x0, csvNum:"", Reference:"[Wesley_Craig]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoIDPR-CMTP0 := &protos.IPProto{Name:"IDPR-CMTP", Description:"IDPR Control Message Transport Proto", Number:0x0, csvNum:"", Reference:"[Martha_Steenstrup]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoIDPR-CMTP0 = &IPProto{Name:"IDPR-CMTP", Description:"IDPR Control Message Transport Proto", Number:0x0, csvNum:"", Reference:"[Martha_Steenstrup]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoTP++0 := &protos.IPProto{Name:"TP++", Description:"TP++ Transport Protocol", Number:0x0, csvNum:"", Reference:"[Dirk_Fromhein]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoTP++0 = &IPProto{Name:"TP++", Description:"TP++ Transport Protocol", Number:0x0, csvNum:"", Reference:"[Dirk_Fromhein]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoIL0 := &protos.IPProto{Name:"IL", Description:"IL Transport Protocol", Number:0x0, csvNum:"", Reference:"[Dave_Presotto]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoIL0 = &IPProto{Name:"IL", Description:"IL Transport Protocol", Number:0x0, csvNum:"", Reference:"[Dave_Presotto]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoIPv60 := &protos.IPProto{Name:"IPv6", Description:"IPv6 encapsulation", Number:0x0, csvNum:"", Reference:"[RFC2473]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoIPv60 = &IPProto{Name:"IPv6", Description:"IPv6 encapsulation", Number:0x0, csvNum:"", Reference:"[RFC2473]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoSDRP0 := &protos.IPProto{Name:"SDRP", Description:"Source Demand Routing Protocol", Number:0x0, csvNum:"", Reference:"[Deborah_Estrin]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoSDRP0 = &IPProto{Name:"SDRP", Description:"Source Demand Routing Protocol", Number:0x0, csvNum:"", Reference:"[Deborah_Estrin]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoIPv6-Route0 := &protos.IPProto{Name:"IPv6-Route", Description:"Routing Header for IPv6", Number:0x0, csvNum:"", Reference:"[Steve_Deering]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoIPv6-Route0 = &IPProto{Name:"IPv6-Route", Description:"Routing Header for IPv6", Number:0x0, csvNum:"", Reference:"[Steve_Deering]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoIPv6-Frag0 := &protos.IPProto{Name:"IPv6-Frag", Description:"Fragment Header for IPv6", Number:0x0, csvNum:"", Reference:"[Steve_Deering]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoIPv6-Frag0 = &IPProto{Name:"IPv6-Frag", Description:"Fragment Header for IPv6", Number:0x0, csvNum:"", Reference:"[Steve_Deering]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoIDRP0 := &protos.IPProto{Name:"IDRP", Description:"Inter-Domain Routing Protocol", Number:0x0, csvNum:"", Reference:"[Sue_Hares]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoIDRP0 = &IPProto{Name:"IDRP", Description:"Inter-Domain Routing Protocol", Number:0x0, csvNum:"", Reference:"[Sue_Hares]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoRSVP0 := &protos.IPProto{Name:"RSVP", Description:"Reservation Protocol", Number:0x0, csvNum:"", Reference:"[RFC2205][RFC3209][Bob_Braden]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoRSVP0 = &IPProto{Name:"RSVP", Description:"Reservation Protocol", Number:0x0, csvNum:"", Reference:"[RFC2205][RFC3209][Bob_Braden]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoGRE0 := &protos.IPProto{Name:"GRE", Description:"Generic Routing Encapsulation", Number:0x0, csvNum:"", Reference:"[RFC2784][Tony_Li]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoGRE0 = &IPProto{Name:"GRE", Description:"Generic Routing Encapsulation", Number:0x0, csvNum:"", Reference:"[RFC2784][Tony_Li]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoDSR0 := &protos.IPProto{Name:"DSR", Description:"Dynamic Source Routing Protocol", Number:0x0, csvNum:"", Reference:"[RFC4728]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoDSR0 = &IPProto{Name:"DSR", Description:"Dynamic Source Routing Protocol", Number:0x0, csvNum:"", Reference:"[RFC4728]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoBNA0 := &protos.IPProto{Name:"BNA", Description:"BNA", Number:0x0, csvNum:"", Reference:"[Gary Salamon]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoBNA0 = &IPProto{Name:"BNA", Description:"BNA", Number:0x0, csvNum:"", Reference:"[Gary Salamon]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoESP0 := &protos.IPProto{Name:"ESP", Description:"Encap Security Payload", Number:0x0, csvNum:"", Reference:"[RFC4303]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoESP0 = &IPProto{Name:"ESP", Description:"Encap Security Payload", Number:0x0, csvNum:"", Reference:"[RFC4303]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoAH0 := &protos.IPProto{Name:"AH", Description:"Authentication Header", Number:0x0, csvNum:"", Reference:"[RFC4302]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoAH0 = &IPProto{Name:"AH", Description:"Authentication Header", Number:0x0, csvNum:"", Reference:"[RFC4302]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoI-NLSP0 := &protos.IPProto{Name:"I-NLSP", Description:"Integrated Net Layer Security TUBA", Number:0x0, csvNum:"", Reference:"[K_Robert_Glenn]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoI-NLSP0 = &IPProto{Name:"I-NLSP", Description:"Integrated Net Layer Security TUBA", Number:0x0, csvNum:"", Reference:"[K_Robert_Glenn]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoSWIPE (deprecated)0 := &protos.IPProto{Name:"SWIPE (deprecated)", Description:"IP with Encryption", Number:0x0, csvNum:"", Reference:"[John_Ioannidis]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoSWIPE (deprecated)0 = &IPProto{Name:"SWIPE (deprecated)", Description:"IP with Encryption", Number:0x0, csvNum:"", Reference:"[John_Ioannidis]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoNARP0 := &protos.IPProto{Name:"NARP", Description:"NBMA Address Resolution Protocol", Number:0x0, csvNum:"", Reference:"[RFC1735]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoNARP0 = &IPProto{Name:"NARP", Description:"NBMA Address Resolution Protocol", Number:0x0, csvNum:"", Reference:"[RFC1735]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoMOBILE0 := &protos.IPProto{Name:"MOBILE", Description:"IP Mobility", Number:0x0, csvNum:"", Reference:"[Charlie_Perkins]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoMOBILE0 = &IPProto{Name:"MOBILE", Description:"IP Mobility", Number:0x0, csvNum:"", Reference:"[Charlie_Perkins]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoTLSP0 := &protos.IPProto{Name:"TLSP", Description:"Transport Layer Security Protocol \nusing Kryptonet key management", Number:0x0, csvNum:"", Reference:"[Christer_Oberg]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoTLSP0 = &IPProto{Name:"TLSP", Description:"Transport Layer Security Protocol \nusing Kryptonet key management", Number:0x0, csvNum:"", Reference:"[Christer_Oberg]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoSKIP0 := &protos.IPProto{Name:"SKIP", Description:"SKIP", Number:0x0, csvNum:"", Reference:"[Tom_Markson]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoSKIP0 = &IPProto{Name:"SKIP", Description:"SKIP", Number:0x0, csvNum:"", Reference:"[Tom_Markson]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoIPv6-ICMP0 := &protos.IPProto{Name:"IPv6-ICMP", Description:"ICMP for IPv6", Number:0x0, csvNum:"", Reference:"[RFC8200]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoIPv6-ICMP0 = &IPProto{Name:"IPv6-ICMP", Description:"ICMP for IPv6", Number:0x0, csvNum:"", Reference:"[RFC8200]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoIPv6-NoNxt0 := &protos.IPProto{Name:"IPv6-NoNxt", Description:"No Next Header for IPv6", Number:0x0, csvNum:"", Reference:"[RFC8200]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoIPv6-NoNxt0 = &IPProto{Name:"IPv6-NoNxt", Description:"No Next Header for IPv6", Number:0x0, csvNum:"", Reference:"[RFC8200]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoIPv6-Opts0 := &protos.IPProto{Name:"IPv6-Opts", Description:"Destination Options for IPv6", Number:0x0, csvNum:"", Reference:"[RFC8200]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoIPv6-Opts0 = &IPProto{Name:"IPv6-Opts", Description:"Destination Options for IPv6", Number:0x0, csvNum:"", Reference:"[RFC8200]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProto0 := &protos.IPProto{Name:"", Description:"any host internal protocol", Number:0x0, csvNum:"", Reference:"[Internet_Assigned_Numbers_Authority]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProto0 = &IPProto{Name:"", Description:"any host internal protocol", Number:0x0, csvNum:"", Reference:"[Internet_Assigned_Numbers_Authority]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoCFTP0 := &protos.IPProto{Name:"CFTP", Description:"CFTP", Number:0x0, csvNum:"", Reference:"[Forsdick, H., \"CFTP\", Network Message, Bolt Beranek and\nNewman, January 1982.][Harry_Forsdick]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoCFTP0 = &IPProto{Name:"CFTP", Description:"CFTP", Number:0x0, csvNum:"", Reference:"[Forsdick, H., \"CFTP\", Network Message, Bolt Beranek and\nNewman, January 1982.][Harry_Forsdick]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProto0 := &protos.IPProto{Name:"", Description:"any local network", Number:0x0, csvNum:"", Reference:"[Internet_Assigned_Numbers_Authority]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProto0 = &IPProto{Name:"", Description:"any local network", Number:0x0, csvNum:"", Reference:"[Internet_Assigned_Numbers_Authority]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoSAT-EXPAK0 := &protos.IPProto{Name:"SAT-EXPAK", Description:"SATNET and Backroom EXPAK", Number:0x0, csvNum:"", Reference:"[Steven_Blumenthal]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoSAT-EXPAK0 = &IPProto{Name:"SAT-EXPAK", Description:"SATNET and Backroom EXPAK", Number:0x0, csvNum:"", Reference:"[Steven_Blumenthal]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoKRYPTOLAN0 := &protos.IPProto{Name:"KRYPTOLAN", Description:"Kryptolan", Number:0x0, csvNum:"", Reference:"[Paul Liu]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoKRYPTOLAN0 = &IPProto{Name:"KRYPTOLAN", Description:"Kryptolan", Number:0x0, csvNum:"", Reference:"[Paul Liu]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoRVD0 := &protos.IPProto{Name:"RVD", Description:"MIT Remote Virtual Disk Protocol", Number:0x0, csvNum:"", Reference:"[Michael_Greenwald]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoRVD0 = &IPProto{Name:"RVD", Description:"MIT Remote Virtual Disk Protocol", Number:0x0, csvNum:"", Reference:"[Michael_Greenwald]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoIPPC0 := &protos.IPProto{Name:"IPPC", Description:"Internet Pluribus Packet Core", Number:0x0, csvNum:"", Reference:"[Steven_Blumenthal]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoIPPC0 = &IPProto{Name:"IPPC", Description:"Internet Pluribus Packet Core", Number:0x0, csvNum:"", Reference:"[Steven_Blumenthal]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProto0 := &protos.IPProto{Name:"", Description:"any distributed file system", Number:0x0, csvNum:"", Reference:"[Internet_Assigned_Numbers_Authority]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProto0 = &IPProto{Name:"", Description:"any distributed file system", Number:0x0, csvNum:"", Reference:"[Internet_Assigned_Numbers_Authority]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoSAT-MON0 := &protos.IPProto{Name:"SAT-MON", Description:"SATNET Monitoring", Number:0x0, csvNum:"", Reference:"[Steven_Blumenthal]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoSAT-MON0 = &IPProto{Name:"SAT-MON", Description:"SATNET Monitoring", Number:0x0, csvNum:"", Reference:"[Steven_Blumenthal]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoVISA0 := &protos.IPProto{Name:"VISA", Description:"VISA Protocol", Number:0x0, csvNum:"", Reference:"[Gene_Tsudik]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoVISA0 = &IPProto{Name:"VISA", Description:"VISA Protocol", Number:0x0, csvNum:"", Reference:"[Gene_Tsudik]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoIPCV0 := &protos.IPProto{Name:"IPCV", Description:"Internet Packet Core Utility", Number:0x0, csvNum:"", Reference:"[Steven_Blumenthal]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoIPCV0 = &IPProto{Name:"IPCV", Description:"Internet Packet Core Utility", Number:0x0, csvNum:"", Reference:"[Steven_Blumenthal]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoCPNX0 := &protos.IPProto{Name:"CPNX", Description:"Computer Protocol Network Executive", Number:0x0, csvNum:"", Reference:"[David Mittnacht]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoCPNX0 = &IPProto{Name:"CPNX", Description:"Computer Protocol Network Executive", Number:0x0, csvNum:"", Reference:"[David Mittnacht]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoCPHB0 := &protos.IPProto{Name:"CPHB", Description:"Computer Protocol Heart Beat", Number:0x0, csvNum:"", Reference:"[David Mittnacht]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoCPHB0 = &IPProto{Name:"CPHB", Description:"Computer Protocol Heart Beat", Number:0x0, csvNum:"", Reference:"[David Mittnacht]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoWSN0 := &protos.IPProto{Name:"WSN", Description:"Wang Span Network", Number:0x0, csvNum:"", Reference:"[Victor Dafoulas]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoWSN0 = &IPProto{Name:"WSN", Description:"Wang Span Network", Number:0x0, csvNum:"", Reference:"[Victor Dafoulas]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoPVP0 := &protos.IPProto{Name:"PVP", Description:"Packet Video Protocol", Number:0x0, csvNum:"", Reference:"[Steve_Casner]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoPVP0 = &IPProto{Name:"PVP", Description:"Packet Video Protocol", Number:0x0, csvNum:"", Reference:"[Steve_Casner]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoBR-SAT-MON0 := &protos.IPProto{Name:"BR-SAT-MON", Description:"Backroom SATNET Monitoring", Number:0x0, csvNum:"", Reference:"[Steven_Blumenthal]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoBR-SAT-MON0 = &IPProto{Name:"BR-SAT-MON", Description:"Backroom SATNET Monitoring", Number:0x0, csvNum:"", Reference:"[Steven_Blumenthal]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoSUN-ND0 := &protos.IPProto{Name:"SUN-ND", Description:"SUN ND PROTOCOL-Temporary", Number:0x0, csvNum:"", Reference:"[William_Melohn]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoSUN-ND0 = &IPProto{Name:"SUN-ND", Description:"SUN ND PROTOCOL-Temporary", Number:0x0, csvNum:"", Reference:"[William_Melohn]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoWB-MON0 := &protos.IPProto{Name:"WB-MON", Description:"WIDEBAND Monitoring", Number:0x0, csvNum:"", Reference:"[Steven_Blumenthal]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoWB-MON0 = &IPProto{Name:"WB-MON", Description:"WIDEBAND Monitoring", Number:0x0, csvNum:"", Reference:"[Steven_Blumenthal]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoWB-EXPAK0 := &protos.IPProto{Name:"WB-EXPAK", Description:"WIDEBAND EXPAK", Number:0x0, csvNum:"", Reference:"[Steven_Blumenthal]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoWB-EXPAK0 = &IPProto{Name:"WB-EXPAK", Description:"WIDEBAND EXPAK", Number:0x0, csvNum:"", Reference:"[Steven_Blumenthal]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoISO-IP0 := &protos.IPProto{Name:"ISO-IP", Description:"ISO Internet Protocol", Number:0x0, csvNum:"", Reference:"[Marshall_T_Rose]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoISO-IP0 = &IPProto{Name:"ISO-IP", Description:"ISO Internet Protocol", Number:0x0, csvNum:"", Reference:"[Marshall_T_Rose]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoVMTP0 := &protos.IPProto{Name:"VMTP", Description:"VMTP", Number:0x0, csvNum:"", Reference:"[Dave_Cheriton]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoVMTP0 = &IPProto{Name:"VMTP", Description:"VMTP", Number:0x0, csvNum:"", Reference:"[Dave_Cheriton]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoSECURE-VMTP0 := &protos.IPProto{Name:"SECURE-VMTP", Description:"SECURE-VMTP", Number:0x0, csvNum:"", Reference:"[Dave_Cheriton]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoSECURE-VMTP0 = &IPProto{Name:"SECURE-VMTP", Description:"SECURE-VMTP", Number:0x0, csvNum:"", Reference:"[Dave_Cheriton]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoVINES0 := &protos.IPProto{Name:"VINES", Description:"VINES", Number:0x0, csvNum:"", Reference:"[Brian Horn]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoVINES0 = &IPProto{Name:"VINES", Description:"VINES", Number:0x0, csvNum:"", Reference:"[Brian Horn]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoTTP0 := &protos.IPProto{Name:"TTP", Description:"Transaction Transport Protocol", Number:0x0, csvNum:"", Reference:"[Jim_Stevens]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoTTP0 = &IPProto{Name:"TTP", Description:"Transaction Transport Protocol", Number:0x0, csvNum:"", Reference:"[Jim_Stevens]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoIPTM0 := &protos.IPProto{Name:"IPTM", Description:"Internet Protocol Traffic Manager", Number:0x0, csvNum:"", Reference:"[Jim_Stevens]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoIPTM0 = &IPProto{Name:"IPTM", Description:"Internet Protocol Traffic Manager", Number:0x0, csvNum:"", Reference:"[Jim_Stevens]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoNSFNET-IGP0 := &protos.IPProto{Name:"NSFNET-IGP", Description:"NSFNET-IGP", Number:0x0, csvNum:"", Reference:"[Hans_Werner_Braun]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoNSFNET-IGP0 = &IPProto{Name:"NSFNET-IGP", Description:"NSFNET-IGP", Number:0x0, csvNum:"", Reference:"[Hans_Werner_Braun]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoDGP0 := &protos.IPProto{Name:"DGP", Description:"Dissimilar Gateway Protocol", Number:0x0, csvNum:"", Reference:"[M/A-COM Government Systems, \"Dissimilar Gateway Protocol\nSpecification, Draft Version\", Contract no. CS901145,\nNovember 16, 1987.][Mike_Little]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoDGP0 = &IPProto{Name:"DGP", Description:"Dissimilar Gateway Protocol", Number:0x0, csvNum:"", Reference:"[M/A-COM Government Systems, \"Dissimilar Gateway Protocol\nSpecification, Draft Version\", Contract no. CS901145,\nNovember 16, 1987.][Mike_Little]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoTCF0 := &protos.IPProto{Name:"TCF", Description:"TCF", Number:0x0, csvNum:"", Reference:"[Guillermo_A_Loyola]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoTCF0 = &IPProto{Name:"TCF", Description:"TCF", Number:0x0, csvNum:"", Reference:"[Guillermo_A_Loyola]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoEIGRP0 := &protos.IPProto{Name:"EIGRP", Description:"EIGRP", Number:0x0, csvNum:"", Reference:"[RFC7868]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoEIGRP0 = &IPProto{Name:"EIGRP", Description:"EIGRP", Number:0x0, csvNum:"", Reference:"[RFC7868]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoOSPFIGP0 := &protos.IPProto{Name:"OSPFIGP", Description:"OSPFIGP", Number:0x0, csvNum:"", Reference:"[RFC1583][RFC2328][RFC5340][John_Moy]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoOSPFIGP0 = &IPProto{Name:"OSPFIGP", Description:"OSPFIGP", Number:0x0, csvNum:"", Reference:"[RFC1583][RFC2328][RFC5340][John_Moy]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoSprite-RPC0 := &protos.IPProto{Name:"Sprite-RPC", Description:"Sprite RPC Protocol", Number:0x0, csvNum:"", Reference:"[Welch, B., \"The Sprite Remote Procedure Call System\",\nTechnical Report, UCB/Computer Science Dept., 86/302,\nUniversity of California at Berkeley, June 1986.][Bruce Willins]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoSprite-RPC0 = &IPProto{Name:"Sprite-RPC", Description:"Sprite RPC Protocol", Number:0x0, csvNum:"", Reference:"[Welch, B., \"The Sprite Remote Procedure Call System\",\nTechnical Report, UCB/Computer Science Dept., 86/302,\nUniversity of California at Berkeley, June 1986.][Bruce Willins]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoLARP0 := &protos.IPProto{Name:"LARP", Description:"Locus Address Resolution Protocol", Number:0x0, csvNum:"", Reference:"[Brian Horn]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoLARP0 = &IPProto{Name:"LARP", Description:"Locus Address Resolution Protocol", Number:0x0, csvNum:"", Reference:"[Brian Horn]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoMTP0 := &protos.IPProto{Name:"MTP", Description:"Multicast Transport Protocol", Number:0x0, csvNum:"", Reference:"[Susie_Armstrong]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoMTP0 = &IPProto{Name:"MTP", Description:"Multicast Transport Protocol", Number:0x0, csvNum:"", Reference:"[Susie_Armstrong]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoAX.250 := &protos.IPProto{Name:"AX.25", Description:"AX.25 Frames", Number:0x0, csvNum:"", Reference:"[Brian_Kantor]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoAX.250 = &IPProto{Name:"AX.25", Description:"AX.25 Frames", Number:0x0, csvNum:"", Reference:"[Brian_Kantor]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoIPIP0 := &protos.IPProto{Name:"IPIP", Description:"IP-within-IP Encapsulation Protocol", Number:0x0, csvNum:"", Reference:"[John_Ioannidis]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoIPIP0 = &IPProto{Name:"IPIP", Description:"IP-within-IP Encapsulation Protocol", Number:0x0, csvNum:"", Reference:"[John_Ioannidis]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoMICP (deprecated)0 := &protos.IPProto{Name:"MICP (deprecated)", Description:"Mobile Internetworking Control Pro.", Number:0x0, csvNum:"", Reference:"[John_Ioannidis]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoMICP (deprecated)0 = &IPProto{Name:"MICP (deprecated)", Description:"Mobile Internetworking Control Pro.", Number:0x0, csvNum:"", Reference:"[John_Ioannidis]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoSCC-SP0 := &protos.IPProto{Name:"SCC-SP", Description:"Semaphore Communications Sec. Pro.", Number:0x0, csvNum:"", Reference:"[Howard_Hart]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoSCC-SP0 = &IPProto{Name:"SCC-SP", Description:"Semaphore Communications Sec. Pro.", Number:0x0, csvNum:"", Reference:"[Howard_Hart]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoETHERIP0 := &protos.IPProto{Name:"ETHERIP", Description:"Ethernet-within-IP Encapsulation", Number:0x0, csvNum:"", Reference:"[RFC3378]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoETHERIP0 = &IPProto{Name:"ETHERIP", Description:"Ethernet-within-IP Encapsulation", Number:0x0, csvNum:"", Reference:"[RFC3378]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoENCAP0 := &protos.IPProto{Name:"ENCAP", Description:"Encapsulation Header", Number:0x0, csvNum:"", Reference:"[RFC1241][Robert_Woodburn]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoENCAP0 = &IPProto{Name:"ENCAP", Description:"Encapsulation Header", Number:0x0, csvNum:"", Reference:"[RFC1241][Robert_Woodburn]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProto0 := &protos.IPProto{Name:"", Description:"any private encryption scheme", Number:0x0, csvNum:"", Reference:"[Internet_Assigned_Numbers_Authority]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProto0 = &IPProto{Name:"", Description:"any private encryption scheme", Number:0x0, csvNum:"", Reference:"[Internet_Assigned_Numbers_Authority]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoGMTP0 := &protos.IPProto{Name:"GMTP", Description:"GMTP", Number:0x0, csvNum:"", Reference:"[[RXB5]]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoGMTP0 = &IPProto{Name:"GMTP", Description:"GMTP", Number:0x0, csvNum:"", Reference:"[[RXB5]]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoIFMP0 := &protos.IPProto{Name:"IFMP", Description:"Ipsilon Flow Management Protocol", Number:0x0, csvNum:"", Reference:"[Bob_Hinden][November 1995, 1997.]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoIFMP0 = &IPProto{Name:"IFMP", Description:"Ipsilon Flow Management Protocol", Number:0x0, csvNum:"", Reference:"[Bob_Hinden][November 1995, 1997.]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoPNNI0 := &protos.IPProto{Name:"PNNI", Description:"PNNI over IP", Number:0x0, csvNum:"", Reference:"[Ross_Callon]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoPNNI0 = &IPProto{Name:"PNNI", Description:"PNNI over IP", Number:0x0, csvNum:"", Reference:"[Ross_Callon]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoPIM0 := &protos.IPProto{Name:"PIM", Description:"Protocol Independent Multicast", Number:0x0, csvNum:"", Reference:"[RFC7761][Dino_Farinacci]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoPIM0 = &IPProto{Name:"PIM", Description:"Protocol Independent Multicast", Number:0x0, csvNum:"", Reference:"[RFC7761][Dino_Farinacci]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoARIS0 := &protos.IPProto{Name:"ARIS", Description:"ARIS", Number:0x0, csvNum:"", Reference:"[Nancy_Feldman]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoARIS0 = &IPProto{Name:"ARIS", Description:"ARIS", Number:0x0, csvNum:"", Reference:"[Nancy_Feldman]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoSCPS0 := &protos.IPProto{Name:"SCPS", Description:"SCPS", Number:0x0, csvNum:"", Reference:"[Robert_Durst]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoSCPS0 = &IPProto{Name:"SCPS", Description:"SCPS", Number:0x0, csvNum:"", Reference:"[Robert_Durst]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoQNX0 := &protos.IPProto{Name:"QNX", Description:"QNX", Number:0x0, csvNum:"", Reference:"[Michael_Hunter]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoQNX0 = &IPProto{Name:"QNX", Description:"QNX", Number:0x0, csvNum:"", Reference:"[Michael_Hunter]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoA/N0 := &protos.IPProto{Name:"A/N", Description:"Active Networks", Number:0x0, csvNum:"", Reference:"[Bob_Braden]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoA/N0 = &IPProto{Name:"A/N", Description:"Active Networks", Number:0x0, csvNum:"", Reference:"[Bob_Braden]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoIPComp0 := &protos.IPProto{Name:"IPComp", Description:"IP Payload Compression Protocol", Number:0x0, csvNum:"", Reference:"[RFC2393]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoIPComp0 = &IPProto{Name:"IPComp", Description:"IP Payload Compression Protocol", Number:0x0, csvNum:"", Reference:"[RFC2393]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoSNP0 := &protos.IPProto{Name:"SNP", Description:"Sitara Networks Protocol", Number:0x0, csvNum:"", Reference:"[Manickam_R_Sridhar]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoSNP0 = &IPProto{Name:"SNP", Description:"Sitara Networks Protocol", Number:0x0, csvNum:"", Reference:"[Manickam_R_Sridhar]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoCompaq-Peer0 := &protos.IPProto{Name:"Compaq-Peer", Description:"Compaq Peer Protocol", Number:0x0, csvNum:"", Reference:"[Victor_Volpe]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoCompaq-Peer0 = &IPProto{Name:"Compaq-Peer", Description:"Compaq Peer Protocol", Number:0x0, csvNum:"", Reference:"[Victor_Volpe]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoIPX-in-IP0 := &protos.IPProto{Name:"IPX-in-IP", Description:"IPX in IP", Number:0x0, csvNum:"", Reference:"[CJ_Lee]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoIPX-in-IP0 = &IPProto{Name:"IPX-in-IP", Description:"IPX in IP", Number:0x0, csvNum:"", Reference:"[CJ_Lee]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoVRRP0 := &protos.IPProto{Name:"VRRP", Description:"Virtual Router Redundancy Protocol", Number:0x0, csvNum:"", Reference:"[RFC5798]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoVRRP0 = &IPProto{Name:"VRRP", Description:"Virtual Router Redundancy Protocol", Number:0x0, csvNum:"", Reference:"[RFC5798]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoPGM0 := &protos.IPProto{Name:"PGM", Description:"PGM Reliable Transport Protocol", Number:0x0, csvNum:"", Reference:"[Tony_Speakman]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoPGM0 = &IPProto{Name:"PGM", Description:"PGM Reliable Transport Protocol", Number:0x0, csvNum:"", Reference:"[Tony_Speakman]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProto0 := &protos.IPProto{Name:"", Description:"any 0-hop protocol", Number:0x0, csvNum:"", Reference:"[Internet_Assigned_Numbers_Authority]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProto0 = &IPProto{Name:"", Description:"any 0-hop protocol", Number:0x0, csvNum:"", Reference:"[Internet_Assigned_Numbers_Authority]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoL2TP0 := &protos.IPProto{Name:"L2TP", Description:"Layer Two Tunneling Protocol", Number:0x0, csvNum:"", Reference:"[RFC3931][Bernard_Aboba]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoL2TP0 = &IPProto{Name:"L2TP", Description:"Layer Two Tunneling Protocol", Number:0x0, csvNum:"", Reference:"[RFC3931][Bernard_Aboba]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoDDX0 := &protos.IPProto{Name:"DDX", Description:"D-II Data Exchange (DDX)", Number:0x0, csvNum:"", Reference:"[John_Worley]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoDDX0 = &IPProto{Name:"DDX", Description:"D-II Data Exchange (DDX)", Number:0x0, csvNum:"", Reference:"[John_Worley]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoIATP0 := &protos.IPProto{Name:"IATP", Description:"Interactive Agent Transfer Protocol", Number:0x0, csvNum:"", Reference:"[John_Murphy]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoIATP0 = &IPProto{Name:"IATP", Description:"Interactive Agent Transfer Protocol", Number:0x0, csvNum:"", Reference:"[John_Murphy]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoSTP0 := &protos.IPProto{Name:"STP", Description:"Schedule Transfer Protocol", Number:0x0, csvNum:"", Reference:"[Jean_Michel_Pittet]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoSTP0 = &IPProto{Name:"STP", Description:"Schedule Transfer Protocol", Number:0x0, csvNum:"", Reference:"[Jean_Michel_Pittet]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoSRP0 := &protos.IPProto{Name:"SRP", Description:"SpectraLink Radio Protocol", Number:0x0, csvNum:"", Reference:"[Mark_Hamilton]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoSRP0 = &IPProto{Name:"SRP", Description:"SpectraLink Radio Protocol", Number:0x0, csvNum:"", Reference:"[Mark_Hamilton]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoUTI0 := &protos.IPProto{Name:"UTI", Description:"UTI", Number:0x0, csvNum:"", Reference:"[Peter_Lothberg]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoUTI0 = &IPProto{Name:"UTI", Description:"UTI", Number:0x0, csvNum:"", Reference:"[Peter_Lothberg]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoSMP0 := &protos.IPProto{Name:"SMP", Description:"Simple Message Protocol", Number:0x0, csvNum:"", Reference:"[Leif_Ekblad]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoSMP0 = &IPProto{Name:"SMP", Description:"Simple Message Protocol", Number:0x0, csvNum:"", Reference:"[Leif_Ekblad]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoSM (deprecated)0 := &protos.IPProto{Name:"SM (deprecated)", Description:"Simple Multicast Protocol", Number:0x0, csvNum:"", Reference:"[Jon_Crowcroft][draft-perlman-simple-multicast]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoSM (deprecated)0 = &IPProto{Name:"SM (deprecated)", Description:"Simple Multicast Protocol", Number:0x0, csvNum:"", Reference:"[Jon_Crowcroft][draft-perlman-simple-multicast]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoPTP0 := &protos.IPProto{Name:"PTP", Description:"Performance Transparency Protocol", Number:0x0, csvNum:"", Reference:"[Michael_Welzl]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoPTP0 = &IPProto{Name:"PTP", Description:"Performance Transparency Protocol", Number:0x0, csvNum:"", Reference:"[Michael_Welzl]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoISIS over IPv40 := &protos.IPProto{Name:"ISIS over IPv4", Description:"", Number:0x0, csvNum:"", Reference:"[Tony_Przygienda]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoISIS over IPv40 = &IPProto{Name:"ISIS over IPv4", Description:"", Number:0x0, csvNum:"", Reference:"[Tony_Przygienda]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoFIRE0 := &protos.IPProto{Name:"FIRE", Description:"", Number:0x0, csvNum:"", Reference:"[Criag_Partridge]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoFIRE0 = &IPProto{Name:"FIRE", Description:"", Number:0x0, csvNum:"", Reference:"[Criag_Partridge]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoCRTP0 := &protos.IPProto{Name:"CRTP", Description:"Combat Radio Transport Protocol", Number:0x0, csvNum:"", Reference:"[Robert_Sautter]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoCRTP0 = &IPProto{Name:"CRTP", Description:"Combat Radio Transport Protocol", Number:0x0, csvNum:"", Reference:"[Robert_Sautter]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoCRUDP0 := &protos.IPProto{Name:"CRUDP", Description:"Combat Radio User Datagram", Number:0x0, csvNum:"", Reference:"[Robert_Sautter]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoCRUDP0 = &IPProto{Name:"CRUDP", Description:"Combat Radio User Datagram", Number:0x0, csvNum:"", Reference:"[Robert_Sautter]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoSSCOPMCE0 := &protos.IPProto{Name:"SSCOPMCE", Description:"", Number:0x0, csvNum:"", Reference:"[Kurt_Waber]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoSSCOPMCE0 = &IPProto{Name:"SSCOPMCE", Description:"", Number:0x0, csvNum:"", Reference:"[Kurt_Waber]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoIPLT0 := &protos.IPProto{Name:"IPLT", Description:"", Number:0x0, csvNum:"", Reference:"[[Hollbach]]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoIPLT0 = &IPProto{Name:"IPLT", Description:"", Number:0x0, csvNum:"", Reference:"[[Hollbach]]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoSPS0 := &protos.IPProto{Name:"SPS", Description:"Secure Packet Shield", Number:0x0, csvNum:"", Reference:"[Bill_McIntosh]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoSPS0 = &IPProto{Name:"SPS", Description:"Secure Packet Shield", Number:0x0, csvNum:"", Reference:"[Bill_McIntosh]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoPIPE0 := &protos.IPProto{Name:"PIPE", Description:"Private IP Encapsulation within IP", Number:0x0, csvNum:"", Reference:"[Bernhard_Petri]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoPIPE0 = &IPProto{Name:"PIPE", Description:"Private IP Encapsulation within IP", Number:0x0, csvNum:"", Reference:"[Bernhard_Petri]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoSCTP0 := &protos.IPProto{Name:"SCTP", Description:"Stream Control Transmission Protocol", Number:0x0, csvNum:"", Reference:"[Randall_R_Stewart]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoSCTP0 = &IPProto{Name:"SCTP", Description:"Stream Control Transmission Protocol", Number:0x0, csvNum:"", Reference:"[Randall_R_Stewart]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoFC0 := &protos.IPProto{Name:"FC", Description:"Fibre Channel", Number:0x0, csvNum:"", Reference:"[Murali_Rajagopal][RFC6172]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoFC0 = &IPProto{Name:"FC", Description:"Fibre Channel", Number:0x0, csvNum:"", Reference:"[Murali_Rajagopal][RFC6172]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoRSVP-E2E-IGNORE0 := &protos.IPProto{Name:"RSVP-E2E-IGNORE", Description:"", Number:0x0, csvNum:"", Reference:"[RFC3175]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoRSVP-E2E-IGNORE0 = &IPProto{Name:"RSVP-E2E-IGNORE", Description:"", Number:0x0, csvNum:"", Reference:"[RFC3175]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoMobility Header0 := &protos.IPProto{Name:"Mobility Header", Description:"", Number:0x0, csvNum:"", Reference:"[RFC6275]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoMobility Header0 = &IPProto{Name:"Mobility Header", Description:"", Number:0x0, csvNum:"", Reference:"[RFC6275]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoUDPLite0 := &protos.IPProto{Name:"UDPLite", Description:"", Number:0x0, csvNum:"", Reference:"[RFC3828]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoUDPLite0 = &IPProto{Name:"UDPLite", Description:"", Number:0x0, csvNum:"", Reference:"[RFC3828]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoMPLS-in-IP0 := &protos.IPProto{Name:"MPLS-in-IP", Description:"", Number:0x0, csvNum:"", Reference:"[RFC4023]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoMPLS-in-IP0 = &IPProto{Name:"MPLS-in-IP", Description:"", Number:0x0, csvNum:"", Reference:"[RFC4023]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtomanet0 := &protos.IPProto{Name:"manet", Description:"MANET Protocols", Number:0x0, csvNum:"", Reference:"[RFC5498]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtomanet0 = &IPProto{Name:"manet", Description:"MANET Protocols", Number:0x0, csvNum:"", Reference:"[RFC5498]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoHIP0 := &protos.IPProto{Name:"HIP", Description:"Host Identity Protocol", Number:0x0, csvNum:"", Reference:"[RFC7401]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoHIP0 = &IPProto{Name:"HIP", Description:"Host Identity Protocol", Number:0x0, csvNum:"", Reference:"[RFC7401]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoShim60 := &protos.IPProto{Name:"Shim6", Description:"Shim6 Protocol", Number:0x0, csvNum:"", Reference:"[RFC5533]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoShim60 = &IPProto{Name:"Shim6", Description:"Shim6 Protocol", Number:0x0, csvNum:"", Reference:"[RFC5533]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoWESP0 := &protos.IPProto{Name:"WESP", Description:"Wrapped Encapsulating Security Payload", Number:0x0, csvNum:"", Reference:"[RFC5840]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoWESP0 = &IPProto{Name:"WESP", Description:"Wrapped Encapsulating Security Payload", Number:0x0, csvNum:"", Reference:"[RFC5840]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoROHC0 := &protos.IPProto{Name:"ROHC", Description:"Robust Header Compression", Number:0x0, csvNum:"", Reference:"[RFC5858]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoROHC0 = &IPProto{Name:"ROHC", Description:"Robust Header Compression", Number:0x0, csvNum:"", Reference:"[RFC5858]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoEthernet0 := &protos.IPProto{Name:"Ethernet", Description:"Ethernet", Number:0x0, csvNum:"", Reference:"[RFC-ietf-spring-srv6-network-programming-28]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoEthernet0 = &IPProto{Name:"Ethernet", Description:"Ethernet", Number:0x0, csvNum:"", Reference:"[RFC-ietf-spring-srv6-network-programming-28]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProto0 := &protos.IPProto{Name:"", Description:"Unassigned", Number:0x0, csvNum:"", Reference:"[Internet_Assigned_Numbers_Authority]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProto0 = &IPProto{Name:"", Description:"Unassigned", Number:0x0, csvNum:"", Reference:"[Internet_Assigned_Numbers_Authority]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProto0 := &protos.IPProto{Name:"", Description:"Use for experimentation and testing", Number:0x0, csvNum:"", Reference:"[RFC3692]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProto0 = &IPProto{Name:"", Description:"Use for experimentation and testing", Number:0x0, csvNum:"", Reference:"[RFC3692]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProto0 := &protos.IPProto{Name:"", Description:"Use for experimentation and testing", Number:0x0, csvNum:"", Reference:"[RFC3692]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProto0 = &IPProto{Name:"", Description:"Use for experimentation and testing", Number:0x0, csvNum:"", Reference:"[RFC3692]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
RegisteredProtoReserved0 := &protos.IPProto{Name:"Reserved", Description:"", Number:0x0, csvNum:"", Reference:"[Internet_Assigned_Numbers_Authority]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
RegisteredProtoReserved0 = &IPProto{Name:"Reserved", Description:"", Number:0x0, csvNum:"", Reference:"[Internet_Assigned_Numbers_Authority]", Reserved:false, IP6ExtensionHeader:false, ip6ext:false}
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -7,4 +7,6 @@ type IPProto struct {
|
|||||||
Reference string `csv:"Reference"`
|
Reference string `csv:"Reference"`
|
||||||
Reserved bool `csv:"-"`
|
Reserved bool `csv:"-"`
|
||||||
IP6ExtensionHeader bool `csv:"-"`
|
IP6ExtensionHeader bool `csv:"-"`
|
||||||
|
csvNum string
|
||||||
|
ip6ext bool
|
||||||
}
|
}
|
||||||
|
@ -12,22 +12,4 @@ var (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
StructTagInterpolate string = "envsub"
|
StructTagInterpolate string = "envsub"
|
||||||
StructTagPopulate string = "envpop"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
defaultInterpolateOpts interpolateOpts = interpolateOpts{
|
|
||||||
noMapKey: false,
|
|
||||||
noMapVal: false,
|
|
||||||
}
|
|
||||||
// InterpolateOptNoMapKey is the equivalent of the struct tag `no_map_key` for Interpolate.
|
|
||||||
InterpolateOptNoMapKey optInterpolate = func(o *interpolateOpts) (err error) {
|
|
||||||
o.noMapKey = true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// InterpolateOptNoMapValue is the equivalent of the struct tag `no_map_value` for Interpolate.
|
|
||||||
InterpolateOptNoMapValue optInterpolate = func(o *interpolateOpts) (err error) {
|
|
||||||
o.noMapVal = true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
358
envs/funcs.go
358
envs/funcs.go
@ -11,6 +11,7 @@ import (
|
|||||||
`sync`
|
`sync`
|
||||||
|
|
||||||
`r00t2.io/goutils/multierr`
|
`r00t2.io/goutils/multierr`
|
||||||
|
`r00t2.io/goutils/structutils`
|
||||||
`r00t2.io/sysutils/errs`
|
`r00t2.io/sysutils/errs`
|
||||||
`r00t2.io/sysutils/internal`
|
`r00t2.io/sysutils/internal`
|
||||||
`r00t2.io/sysutils/paths`
|
`r00t2.io/sysutils/paths`
|
||||||
@ -195,7 +196,7 @@ func HasEnv(key string) (envIsSet bool) {
|
|||||||
|
|
||||||
- a string (pointer only)
|
- a string (pointer only)
|
||||||
- a struct (pointer only)
|
- a struct (pointer only)
|
||||||
- a map
|
- a map (applied to both keys *and* values)
|
||||||
- a slice
|
- a slice
|
||||||
|
|
||||||
and performs variable substitution on strings from environment variables.
|
and performs variable substitution on strings from environment variables.
|
||||||
@ -206,30 +207,22 @@ func HasEnv(key string) (envIsSet bool) {
|
|||||||
For structs, the tag name used can be changed by setting the StructTagInterpolate
|
For structs, the tag name used can be changed by setting the StructTagInterpolate
|
||||||
variable in this submodule; the default is `envsub`.
|
variable in this submodule; the default is `envsub`.
|
||||||
If the tag value is "-", the field will be skipped.
|
If the tag value is "-", the field will be skipped.
|
||||||
For map fields within structs, the default is to apply interpolation to both keys and values;
|
For map fields within structs etc., the default is to apply interpolation to both keys and values.
|
||||||
this can be changed with the `no_map_key` and `no_map_value` options (tag values).
|
All other tag value(s) are ignored.
|
||||||
Any other tag value(s) are ignored.
|
|
||||||
|
|
||||||
For maps and slices, Interpolate will recurse into values (e.g. [][]string will work as expected).
|
For maps and slices, Interpolate will recurse into values (e.g. [][]string will work as expected).
|
||||||
|
|
||||||
Supported struct tag options:
|
|
||||||
|
|
||||||
* `no_map_key` - Do not operate on map keys if they are strings or string pointers.
|
|
||||||
See also InterpolateOptNoMapKey.
|
|
||||||
* `no_map_value` - Do not operate on map values if they are strings or string pointers.
|
|
||||||
See also InterpolateOptNoMapValue.
|
|
||||||
|
|
||||||
If s is nil, no interpolation will be performed. No error will be returned.
|
If s is nil, no interpolation will be performed. No error will be returned.
|
||||||
If s is not a valid/supported type, no interpolation will be performed. No error will be returned.
|
If s is not a valid/supported type, no interpolation will be performed. No error will be returned.
|
||||||
*/
|
*/
|
||||||
func Interpolate[T any](s T, opts ...optInterpolate) (err error) {
|
func Interpolate[T any](s T) (err error) {
|
||||||
|
|
||||||
var sVal reflect.Value = reflect.ValueOf(s)
|
|
||||||
var sType reflect.Type = sVal.Type()
|
|
||||||
var kind reflect.Kind = sType.Kind()
|
|
||||||
var ptrVal reflect.Value
|
var ptrVal reflect.Value
|
||||||
var ptrType reflect.Type
|
var ptrType reflect.Type
|
||||||
var ptrKind reflect.Kind
|
var ptrKind reflect.Kind
|
||||||
|
var sVal reflect.Value = reflect.ValueOf(s)
|
||||||
|
var sType reflect.Type = sVal.Type()
|
||||||
|
var kind reflect.Kind = sType.Kind()
|
||||||
|
|
||||||
switch kind {
|
switch kind {
|
||||||
case reflect.Ptr:
|
case reflect.Ptr:
|
||||||
@ -240,30 +233,30 @@ func Interpolate[T any](s T, opts ...optInterpolate) (err error) {
|
|||||||
ptrType = ptrVal.Type()
|
ptrType = ptrVal.Type()
|
||||||
ptrKind = ptrType.Kind()
|
ptrKind = ptrType.Kind()
|
||||||
if ptrKind == reflect.String {
|
if ptrKind == reflect.String {
|
||||||
err = interpolateStringReflect(ptrVal, opts, nil)
|
err = interpolateStringReflect(ptrVal)
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, it should be a struct ptr.
|
// Otherwise, it should be a struct ptr.
|
||||||
if ptrKind != reflect.Struct {
|
if ptrKind != reflect.Struct {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = interpolateStruct(ptrVal, opts, nil)
|
err = interpolateStruct(ptrVal)
|
||||||
}
|
}
|
||||||
case reflect.Map:
|
case reflect.Map:
|
||||||
if sVal.IsNil() || sVal.IsZero() || !sVal.IsValid() {
|
if sVal.IsNil() || sVal.IsZero() || !sVal.IsValid() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = interpolateMap(sVal, opts, nil)
|
err = interpolateMap(sVal)
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
if sVal.IsNil() || sVal.IsZero() || !sVal.IsValid() {
|
if sVal.IsNil() || sVal.IsZero() || !sVal.IsValid() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = interpolateSlice(sVal, opts, nil)
|
err = interpolateSlice(sVal)
|
||||||
/*
|
/*
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
if sVal.IsZero() || !sVal.IsValid() {
|
if sVal.IsZero() || !sVal.IsValid() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = interpolateStruct(sVal, opts, nil)
|
err = interpolateStruct(sVal)
|
||||||
|
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
@ -300,153 +293,11 @@ func InterpolateString(s *string) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// interpolateMap is used by Interpolate for maps. v should be a reflect.Value of a map.
|
||||||
PopulateStruct takes (a pointer to) a struct and performs *population* on it.
|
func interpolateMap(v reflect.Value) (err error) {
|
||||||
Unlike the InterpolateStruct function, this *completely populates* (or *replaces*)
|
|
||||||
a field's value with the specified environment variable; no *substitution* is performed.
|
|
||||||
|
|
||||||
You can change the tag name used by changing the StructTagPopulate variable in this module;
|
|
||||||
the default is `envpop`.
|
|
||||||
|
|
||||||
Tag value format:
|
|
||||||
<tag>:"<VAR NAME>[,<option>,<option>...]"
|
|
||||||
e.g.
|
|
||||||
envpop:"SOMEVAR"
|
|
||||||
envpop:"OTHERVAR,force"
|
|
||||||
envpop:"OTHERVAR,allow_empty"
|
|
||||||
envpop:"OTHERVAR,force,allow_empty"
|
|
||||||
|
|
||||||
If the tag value is "-", or <VAR NAME> is not provided, the field will be explicitly skipped.
|
|
||||||
(This is the default behavior for struct fields not tagged with `envpop`.)
|
|
||||||
|
|
||||||
Recognized options:
|
|
||||||
|
|
||||||
* force - Existing field values that are non-empty strings or non-nil pointers are normally skipped; this option always replaces them.
|
|
||||||
* allow_empty - Normally no replacement will be performed if the specified variable is undefined/not found.
|
|
||||||
This option allows an empty string to be used instead.
|
|
||||||
Not very useful for string fields, but potentially useful for string pointer fields.
|
|
||||||
|
|
||||||
e.g.:
|
|
||||||
|
|
||||||
struct{
|
|
||||||
// If this is an empty string, it will be replaced with the value of $CWD.
|
|
||||||
CurrentDir string `envpop:"CWD"`
|
|
||||||
// This would only populate with $USER if the pointer is nil.
|
|
||||||
UserName *string `envpop:"USER"`
|
|
||||||
// This will *always* replace the field's value with the value of $DISPLAY,
|
|
||||||
// even if not an empty string.
|
|
||||||
// Note the `force` option.
|
|
||||||
Display string `envpop:"DISPLAY,force"`
|
|
||||||
// Likewise, even if not nil, this field's value would be replaced with the value of $SHELL.
|
|
||||||
Shell *string `envpop:"SHELL,force"`
|
|
||||||
// This field will be untouched if non-nil, otherwise it will be a pointer to an empty string
|
|
||||||
// if FOOBAR is undefined.
|
|
||||||
NonExistentVar *string `envpop:"FOOBAR,allow_empty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
If s is nil, nothing will be done and err will be errs.ErrNilPtr.
|
|
||||||
If s is not a pointer to a struct, nothing will be done and err will be errs.ErrBadType.
|
|
||||||
*/
|
|
||||||
func PopulateStruct[T any](s T) (err error) {
|
|
||||||
|
|
||||||
var structVal reflect.Value
|
|
||||||
var structType reflect.Type
|
|
||||||
var field reflect.StructField
|
|
||||||
var fieldVal reflect.Value
|
|
||||||
var tagVal string
|
|
||||||
var valSplit []string
|
|
||||||
var varNm string
|
|
||||||
var varVal string
|
|
||||||
var optsMap map[string]bool
|
|
||||||
var force bool
|
|
||||||
var allowEmpty bool
|
|
||||||
var defined bool
|
|
||||||
|
|
||||||
if reflect.TypeOf(s).Kind() != reflect.Ptr {
|
|
||||||
err = errs.ErrBadType
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
structVal = reflect.ValueOf(s)
|
|
||||||
if structVal.IsNil() || structVal.IsZero() || !structVal.IsValid() {
|
|
||||||
err = errs.ErrNilPtr
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
structVal = reflect.ValueOf(s).Elem()
|
|
||||||
structType = structVal.Type()
|
|
||||||
|
|
||||||
if structType.Kind() != reflect.Struct {
|
|
||||||
err = errs.ErrBadType
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < structVal.NumField(); i++ {
|
|
||||||
field = structType.Field(i)
|
|
||||||
fieldVal = structVal.Field(i)
|
|
||||||
|
|
||||||
// Skip explicitly skipped or non-tagged fields.
|
|
||||||
tagVal = field.Tag.Get(StructTagPopulate)
|
|
||||||
if tagVal == "" || strings.TrimSpace(tagVal) == "-" || strings.HasPrefix(tagVal, "-,") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
fieldVal = structVal.Field(i)
|
|
||||||
if fieldVal.Kind() != reflect.Ptr && fieldVal.Kind() != reflect.String {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
optsMap = make(map[string]bool)
|
|
||||||
valSplit = strings.Split(tagVal, ",")
|
|
||||||
if valSplit == nil || len(valSplit) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
varNm = valSplit[0]
|
|
||||||
if strings.TrimSpace(varNm) == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if len(valSplit) >= 2 {
|
|
||||||
for _, o := range valSplit[1:] {
|
|
||||||
optsMap[o] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
force = optsMap["force"]
|
|
||||||
allowEmpty = optsMap["allow_empty"]
|
|
||||||
|
|
||||||
// if !force && (!fieldVal.IsNil() && !fieldVal.IsZero()) {
|
|
||||||
if !force && !fieldVal.IsZero() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if fieldVal.Kind() == reflect.Ptr {
|
|
||||||
if field.Type.Elem().Kind() != reflect.String {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !fieldVal.CanSet() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
varVal, defined = os.LookupEnv(varNm)
|
|
||||||
if !defined && !allowEmpty {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
switch fieldVal.Kind() {
|
|
||||||
case reflect.Ptr:
|
|
||||||
fieldVal.Set(reflect.ValueOf(&varVal))
|
|
||||||
case reflect.String:
|
|
||||||
fieldVal.SetString(varVal)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// interpolateMap is used by Interpolate and interpolateReflect for maps. v should be a reflect.Value of a map.
|
|
||||||
func interpolateMap(v reflect.Value, opts []optInterpolate, tagOpts []optInterpolate) (err error) {
|
|
||||||
|
|
||||||
var kVal reflect.Value
|
var kVal reflect.Value
|
||||||
|
var vVal reflect.Value
|
||||||
var newMap reflect.Value
|
var newMap reflect.Value
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
var numJobs int
|
var numJobs int
|
||||||
@ -455,7 +306,6 @@ func interpolateMap(v reflect.Value, opts []optInterpolate, tagOpts []optInterpo
|
|||||||
var mErr *multierr.MultiError = multierr.NewMultiError(nil)
|
var mErr *multierr.MultiError = multierr.NewMultiError(nil)
|
||||||
var t reflect.Type = v.Type()
|
var t reflect.Type = v.Type()
|
||||||
var kind reflect.Kind = t.Kind()
|
var kind reflect.Kind = t.Kind()
|
||||||
var valOpts *interpolateOpts = new(interpolateOpts)
|
|
||||||
|
|
||||||
if kind != reflect.Map {
|
if kind != reflect.Map {
|
||||||
err = errs.ErrBadType
|
err = errs.ErrBadType
|
||||||
@ -466,78 +316,54 @@ func interpolateMap(v reflect.Value, opts []optInterpolate, tagOpts []optInterpo
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
*valOpts = defaultInterpolateOpts
|
|
||||||
if opts != nil && len(opts) > 0 {
|
|
||||||
for _, opt := range opts {
|
|
||||||
if err = opt(valOpts); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if tagOpts != nil && len(tagOpts) > 0 {
|
|
||||||
for _, opt := range tagOpts {
|
|
||||||
if err = opt(valOpts); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if valOpts.noMapKey && valOpts.noMapVal {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
numJobs = v.Len()
|
numJobs = v.Len()
|
||||||
errChan = make(chan error, numJobs)
|
errChan = make(chan error, numJobs)
|
||||||
wg.Add(numJobs)
|
wg.Add(numJobs)
|
||||||
|
|
||||||
newMap = reflect.MakeMap(reflect.TypeOf(v.Interface()))
|
newMap = reflect.MakeMap(v.Type())
|
||||||
|
|
||||||
for _, e := range v.MapKeys() {
|
for _, kVal = range v.MapKeys() {
|
||||||
kVal = e
|
vVal = v.MapIndex(kVal)
|
||||||
|
go func(key, val reflect.Value) {
|
||||||
go func(mapK reflect.Value) {
|
|
||||||
var mapErr error
|
var mapErr error
|
||||||
var newKey reflect.Value
|
var newKey reflect.Value
|
||||||
var newVal reflect.Value
|
var newVal reflect.Value
|
||||||
var vVal reflect.Value = v.MapIndex(mapK)
|
|
||||||
|
newKey = reflect.New(key.Type()).Elem()
|
||||||
|
newVal = reflect.New(val.Type()).Elem()
|
||||||
|
|
||||||
|
newKey.Set(key.Convert(newKey.Type()))
|
||||||
|
newVal.Set(val.Convert(newVal.Type()))
|
||||||
|
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
if !valOpts.noMapKey {
|
// key
|
||||||
newKey = reflect.New(reflect.TypeOf(mapK.Interface()))
|
if key.Kind() == reflect.String {
|
||||||
newKey.Set(vVal)
|
if mapErr = interpolateStringReflect(newKey); mapErr != nil {
|
||||||
if mapK.Kind() == reflect.String {
|
errChan <- mapErr
|
||||||
if mapErr = interpolateStringReflect(newKey, opts, nil); mapErr != nil {
|
return
|
||||||
errChan <- mapErr
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if mapErr = interpolateValue(newKey, opts, nil); mapErr != nil {
|
|
||||||
errChan <- mapErr
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
newKey = mapK
|
if mapErr = interpolateValue(newKey); mapErr != nil {
|
||||||
|
errChan <- mapErr
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if !valOpts.noMapVal {
|
// value
|
||||||
newVal = reflect.New(vVal.Type())
|
if val.Kind() == reflect.String {
|
||||||
newVal.Set(vVal)
|
if mapErr = interpolateStringReflect(newVal); mapErr != nil {
|
||||||
if vVal.Kind() == reflect.String {
|
errChan <- mapErr
|
||||||
if mapErr = interpolateStringReflect(newVal, opts, nil); mapErr != nil {
|
return
|
||||||
errChan <- mapErr
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if mapErr = interpolateValue(newVal, opts, nil); mapErr != nil {
|
|
||||||
errChan <- mapErr
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
newVal = vVal
|
if mapErr = interpolateValue(newVal); mapErr != nil {
|
||||||
|
errChan <- mapErr
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
newMap.SetMapIndex(reflect.ValueOf(newKey), reflect.ValueOf(newVal))
|
|
||||||
}(kVal)
|
newMap.SetMapIndex(newKey.Convert(key.Type()), newVal.Convert(key.Type()))
|
||||||
|
}(kVal, vVal)
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
@ -560,13 +386,13 @@ func interpolateMap(v reflect.Value, opts []optInterpolate, tagOpts []optInterpo
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
v.Set(newMap)
|
v.Set(newMap.Convert(v.Type()))
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// interpolateSlice is used by Interpolate and interpolateReflect for slices. v should be a reflect.Value of a slice.
|
// interpolateSlice is used by Interpolate for slices and arrays. v should be a reflect.Value of a slice/array.
|
||||||
func interpolateSlice(v reflect.Value, opts []optInterpolate, tagOpts []optInterpolate) (err error) {
|
func interpolateSlice(v reflect.Value) (err error) {
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
var errChan chan error
|
var errChan chan error
|
||||||
@ -575,28 +401,21 @@ func interpolateSlice(v reflect.Value, opts []optInterpolate, tagOpts []optInter
|
|||||||
var mErr *multierr.MultiError = multierr.NewMultiError(nil)
|
var mErr *multierr.MultiError = multierr.NewMultiError(nil)
|
||||||
var t reflect.Type = v.Type()
|
var t reflect.Type = v.Type()
|
||||||
var kind reflect.Kind = t.Kind()
|
var kind reflect.Kind = t.Kind()
|
||||||
var valOpts *interpolateOpts = new(interpolateOpts)
|
|
||||||
|
|
||||||
return
|
switch kind {
|
||||||
|
case reflect.Slice:
|
||||||
if kind != reflect.Slice {
|
if v.IsNil() || v.IsZero() || !v.IsValid() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case reflect.Array:
|
||||||
|
if v.IsZero() || !v.IsValid() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
default:
|
||||||
err = errs.ErrBadType
|
err = errs.ErrBadType
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if v.IsNil() || v.IsZero() || !v.IsValid() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
*valOpts = defaultInterpolateOpts
|
|
||||||
if opts != nil && len(opts) > 0 {
|
|
||||||
for _, opt := range opts {
|
|
||||||
if err = opt(valOpts); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
numJobs = v.Len()
|
numJobs = v.Len()
|
||||||
errChan = make(chan error, numJobs)
|
errChan = make(chan error, numJobs)
|
||||||
wg.Add(numJobs)
|
wg.Add(numJobs)
|
||||||
@ -604,24 +423,20 @@ func interpolateSlice(v reflect.Value, opts []optInterpolate, tagOpts []optInter
|
|||||||
for i := 0; i < v.Len(); i++ {
|
for i := 0; i < v.Len(); i++ {
|
||||||
go func(idx int) {
|
go func(idx int) {
|
||||||
var sErr error
|
var sErr error
|
||||||
var newVal reflect.Value
|
|
||||||
|
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
newVal = reflect.New(v.Index(idx).Type())
|
|
||||||
newVal.Set(v.Index(idx))
|
|
||||||
if v.Index(idx).Kind() == reflect.String {
|
if v.Index(idx).Kind() == reflect.String {
|
||||||
if sErr = interpolateStringReflect(newVal, opts, tagOpts); sErr != nil {
|
if sErr = interpolateStringReflect(v.Index(idx)); sErr != nil {
|
||||||
errChan <- sErr
|
errChan <- sErr
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if sErr = interpolateValue(newVal, opts, tagOpts); sErr != nil {
|
if sErr = interpolateValue(v.Index(idx)); sErr != nil {
|
||||||
errChan <- sErr
|
errChan <- sErr
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
v.Index(idx).Set(reflect.ValueOf(newVal))
|
|
||||||
}(i)
|
}(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -649,10 +464,15 @@ func interpolateSlice(v reflect.Value, opts []optInterpolate, tagOpts []optInter
|
|||||||
}
|
}
|
||||||
|
|
||||||
// interpolateStringReflect is used for structs/nested strings using reflection.
|
// interpolateStringReflect is used for structs/nested strings using reflection.
|
||||||
func interpolateStringReflect(v reflect.Value, opts []optInterpolate, tagOpts []optInterpolate) (err error) {
|
func interpolateStringReflect(v reflect.Value) (err error) {
|
||||||
|
|
||||||
var strVal string
|
var strVal string
|
||||||
|
|
||||||
|
if v.Kind() != reflect.String {
|
||||||
|
err = errs.ErrBadType
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if strVal, err = interpolateString(v.String()); err != nil {
|
if strVal, err = interpolateString(v.String()); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -662,8 +482,8 @@ func interpolateStringReflect(v reflect.Value, opts []optInterpolate, tagOpts []
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// interpolateStruct is used by Interpolate and interpolateReflect for structs. v should be a reflect.Value of a struct.
|
// interpolateStruct is used by Interpolate for structs. v should be a reflect.Value of a struct.
|
||||||
func interpolateStruct(v reflect.Value, opts []optInterpolate, tagOpts []optInterpolate) (err error) {
|
func interpolateStruct(v reflect.Value) (err error) {
|
||||||
|
|
||||||
var field reflect.StructField
|
var field reflect.StructField
|
||||||
var fieldVal reflect.Value
|
var fieldVal reflect.Value
|
||||||
@ -693,7 +513,7 @@ func interpolateStruct(v reflect.Value, opts []optInterpolate, tagOpts []optInte
|
|||||||
|
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
if fErr = interpolateStructField(f, fv, opts, nil); fErr != nil {
|
if fErr = interpolateStructField(f, fv); fErr != nil {
|
||||||
errChan <- fErr
|
errChan <- fErr
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -724,45 +544,31 @@ func interpolateStruct(v reflect.Value, opts []optInterpolate, tagOpts []optInte
|
|||||||
}
|
}
|
||||||
|
|
||||||
// interpolateStructField interpolates a struct field.
|
// interpolateStructField interpolates a struct field.
|
||||||
func interpolateStructField(field reflect.StructField, v reflect.Value, opts []optInterpolate, tagOpts []optInterpolate) (err error) {
|
func interpolateStructField(field reflect.StructField, v reflect.Value) (err error) {
|
||||||
|
|
||||||
var tagVal string
|
|
||||||
// var ftKind reflect.Kind = field.Type.Kind()
|
|
||||||
var parsedTagOpts map[string]bool
|
var parsedTagOpts map[string]bool
|
||||||
var valOpts *interpolateOpts = new(interpolateOpts)
|
|
||||||
|
|
||||||
if !v.CanSet() {
|
if !v.CanSet() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
*valOpts = defaultInterpolateOpts
|
|
||||||
|
|
||||||
// Skip if explicitly instructed to do so.
|
// Skip if explicitly instructed to do so.
|
||||||
tagVal = field.Tag.Get(StructTagInterpolate)
|
parsedTagOpts = structutils.TagToBoolMap(field, StructTagInterpolate, structutils.TagMapTrim)
|
||||||
parsedTagOpts = internal.StringToMapBool(tagVal)
|
|
||||||
if parsedTagOpts["-"] {
|
if parsedTagOpts["-"] {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts != nil && len(opts) > 0 {
|
|
||||||
for _, opt := range opts {
|
|
||||||
if err = opt(valOpts); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if v.Kind() == reflect.Ptr {
|
if v.Kind() == reflect.Ptr {
|
||||||
err = interpolateStructField(field, v.Elem(), opts, tagOpts)
|
err = interpolateStructField(field, v.Elem())
|
||||||
} else {
|
} else {
|
||||||
err = interpolateValue(v, opts, tagOpts)
|
err = interpolateValue(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// interpolateValue is a dispatcher for a reflect value.
|
// interpolateValue is a dispatcher for a reflect value.
|
||||||
func interpolateValue(v reflect.Value, opts []optInterpolate, tagOpts []optInterpolate) (err error) {
|
func interpolateValue(v reflect.Value) (err error) {
|
||||||
|
|
||||||
var kind reflect.Kind = v.Kind()
|
var kind reflect.Kind = v.Kind()
|
||||||
|
|
||||||
@ -772,23 +578,23 @@ func interpolateValue(v reflect.Value, opts []optInterpolate, tagOpts []optInter
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
v = v.Elem()
|
v = v.Elem()
|
||||||
if err = interpolateValue(v, opts, tagOpts); err != nil {
|
if err = interpolateValue(v); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
if err = interpolateStringReflect(v, opts, tagOpts); err != nil {
|
if err = interpolateStringReflect(v); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
case reflect.Slice:
|
case reflect.Slice, reflect.Array:
|
||||||
if err = interpolateSlice(v, opts, tagOpts); err != nil {
|
if err = interpolateSlice(v); err != nil {
|
||||||
}
|
}
|
||||||
case reflect.Map:
|
case reflect.Map:
|
||||||
if err = interpolateMap(v, opts, tagOpts); err != nil {
|
if err = interpolateMap(v); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
if err = interpolateStruct(v, opts, tagOpts); err != nil {
|
if err = interpolateStruct(v); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,825 +0,0 @@
|
|||||||
package envs
|
|
||||||
|
|
||||||
import (
|
|
||||||
`bytes`
|
|
||||||
`errors`
|
|
||||||
`fmt`
|
|
||||||
`io/ioutil`
|
|
||||||
`os`
|
|
||||||
`reflect`
|
|
||||||
`strings`
|
|
||||||
`sync`
|
|
||||||
|
|
||||||
`r00t2.io/goutils/multierr`
|
|
||||||
`r00t2.io/sysutils/errs`
|
|
||||||
`r00t2.io/sysutils/internal`
|
|
||||||
`r00t2.io/sysutils/paths`
|
|
||||||
)
|
|
||||||
|
|
||||||
// GetEnvMap returns a map of all environment variables. All values are strings.
|
|
||||||
func GetEnvMap() (envVars map[string]string) {
|
|
||||||
|
|
||||||
var envList []string = os.Environ()
|
|
||||||
|
|
||||||
envVars = envListToMap(envList)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
GetEnvMapNative returns a map of all environment variables, but attempts to "nativize" them.
|
|
||||||
All values are interfaces. It is up to the caller to typeswitch them to proper types.
|
|
||||||
|
|
||||||
Note that the PATH/Path environment variable (for *Nix and Windows, respectively) will be
|
|
||||||
a []string (as per GetPathEnv). No other env vars, even if they contain os.PathListSeparator,
|
|
||||||
will be transformed to a slice or the like.
|
|
||||||
If an error occurs during parsing the path env var, it will be rendered as a string.
|
|
||||||
|
|
||||||
All number types will attempt to be their 64-bit version (i.e. int64, uint64, float64, etc.).
|
|
||||||
|
|
||||||
If a type cannot be determined for a value, its string form will be used
|
|
||||||
(as it would be found in GetEnvMap).
|
|
||||||
*/
|
|
||||||
func GetEnvMapNative() (envMap map[string]interface{}) {
|
|
||||||
|
|
||||||
var stringMap map[string]string = GetEnvMap()
|
|
||||||
|
|
||||||
envMap = nativizeEnvMap(stringMap)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
GetFirst gets the first instance if populated/set occurrence of varNames.
|
|
||||||
|
|
||||||
For example, if you have three potential env vars, FOO, FOOBAR, FOOBARBAZ,
|
|
||||||
and want to follow the logic flow of:
|
|
||||||
|
|
||||||
1.) Check if FOO is set. If not,
|
|
||||||
2.) Check if FOOBAR is set. If not,
|
|
||||||
3.) Check if FOOBARBAZ is set.
|
|
||||||
|
|
||||||
Then this would be specified as:
|
|
||||||
|
|
||||||
GetFirst([]string{"FOO", "FOOBAR", "FOOBARBAZ"})
|
|
||||||
|
|
||||||
If val is "" and ok is true, this means that one of the specified variable names IS
|
|
||||||
set but is set to an empty value. If ok is false, none of the specified variables
|
|
||||||
are set.
|
|
||||||
|
|
||||||
It is a thin wrapper around GetFirstWithRef.
|
|
||||||
*/
|
|
||||||
func GetFirst(varNames []string) (val string, ok bool) {
|
|
||||||
|
|
||||||
val, ok, _ = GetFirstWithRef(varNames)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
GetFirstWithRef behaves exactly like GetFirst, but with an additional returned value, idx,
|
|
||||||
which specifies the index in varNames in which a set variable was found. e.g. if:
|
|
||||||
|
|
||||||
GetFirstWithRef([]string{"FOO", "FOOBAR", "FOOBAZ"})
|
|
||||||
|
|
||||||
is called and FOO is not set but FOOBAR is, idx will be 1.
|
|
||||||
|
|
||||||
If ok is false, idx will always be -1 and should be ignored.
|
|
||||||
*/
|
|
||||||
func GetFirstWithRef(varNames []string) (val string, ok bool, idx int) {
|
|
||||||
|
|
||||||
idx = -1
|
|
||||||
|
|
||||||
for i, vn := range varNames {
|
|
||||||
if HasEnv(vn) {
|
|
||||||
ok = true
|
|
||||||
idx = i
|
|
||||||
val = os.Getenv(vn)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetPathEnv returns a slice of the PATH variable's items.
|
|
||||||
func GetPathEnv() (pathList []string, err error) {
|
|
||||||
|
|
||||||
var pathVar string = internal.GetPathEnvName()
|
|
||||||
|
|
||||||
pathList = make([]string, 0)
|
|
||||||
|
|
||||||
for _, p := range strings.Split(os.Getenv(pathVar), string(os.PathListSeparator)) {
|
|
||||||
if err = paths.RealPath(&p); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
pathList = append(pathList, p)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
GetPidEnvMap will only work on *NIX-like systems with procfs.
|
|
||||||
It gets the environment variables of a given process' PID.
|
|
||||||
*/
|
|
||||||
func GetPidEnvMap(pid uint32) (envMap map[string]string, err error) {
|
|
||||||
|
|
||||||
var envBytes []byte
|
|
||||||
var envList []string
|
|
||||||
var envArr [][]byte
|
|
||||||
var procPath string
|
|
||||||
var exists bool
|
|
||||||
|
|
||||||
envMap = make(map[string]string, 0)
|
|
||||||
|
|
||||||
procPath = fmt.Sprintf("/proc/%v/environ", pid)
|
|
||||||
|
|
||||||
if exists, err = paths.RealPathExists(&procPath); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !exists {
|
|
||||||
err = errors.New(fmt.Sprintf("information for pid %v does not exist", pid))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if envBytes, err = ioutil.ReadFile(procPath); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
envArr = bytes.Split(envBytes, []byte{0x0})
|
|
||||||
envList = make([]string, len(envArr))
|
|
||||||
for idx, b := range envArr {
|
|
||||||
envList[idx] = string(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
envMap = envListToMap(envList)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
GetPidEnvMapNative, like GetEnvMapNative, returns a map of all environment variables, but attempts to "nativize" them.
|
|
||||||
All values are interfaces. It is up to the caller to typeswitch them to proper types.
|
|
||||||
|
|
||||||
See the documentation for GetEnvMapNative for details.
|
|
||||||
*/
|
|
||||||
func GetPidEnvMapNative(pid uint32) (envMap map[string]interface{}, err error) {
|
|
||||||
|
|
||||||
var stringMap map[string]string
|
|
||||||
|
|
||||||
if stringMap, err = GetPidEnvMap(pid); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
envMap = nativizeEnvMap(stringMap)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
HasEnv is much like os.LookupEnv, but only returns a boolean for
|
|
||||||
if the environment variable key exists or not.
|
|
||||||
|
|
||||||
This is useful anywhere you may need to set a boolean in a func call
|
|
||||||
depending on the *presence* of an env var or not.
|
|
||||||
*/
|
|
||||||
func HasEnv(key string) (envIsSet bool) {
|
|
||||||
|
|
||||||
_, envIsSet = os.LookupEnv(key)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Interpolate takes one of:
|
|
||||||
|
|
||||||
- a string (pointer only)
|
|
||||||
- a struct (pointer only)
|
|
||||||
- a map (comprised of the same requirements)
|
|
||||||
- a slice (comprised of the same requirements)
|
|
||||||
|
|
||||||
and performs variable substitution on strings from environment variables.
|
|
||||||
|
|
||||||
It supports both UNIX/Linux/POSIX syntax formats (e.g. $VARNAME, ${VARNAME}) and,
|
|
||||||
if on Windows, it *additionally* supports the EXPAND_SZ format (e.g. %VARNAME%).
|
|
||||||
|
|
||||||
For structs, the tag name used can be changed by setting the StructTagInterpolate
|
|
||||||
variable in this submodule; the default is `envsub`.
|
|
||||||
If the tag value is "-", the field will be skipped.
|
|
||||||
For map fields within structs, the default is to apply interpolation to both keys and values;
|
|
||||||
this can be changed with the `no_map_key` and `no_map_value` options (tag values).
|
|
||||||
Any other tag value(s) are ignored.
|
|
||||||
|
|
||||||
For maps and slices, Interpolate will recurse into values (e.g. [][]string will work as expected).
|
|
||||||
|
|
||||||
Supported struct tag options:
|
|
||||||
|
|
||||||
* `no_map_key` - Do not operate on map keys if they are strings or string pointers.
|
|
||||||
See also InterpolateOptNoMapKey.
|
|
||||||
* `no_map_value` - Do not operate on map values if they are strings or string pointers.
|
|
||||||
See also InterpolateOptNoMapValue.
|
|
||||||
|
|
||||||
If s is nil, no interpolation will be performed. No error will be returned.
|
|
||||||
If s is not a valid/supported type, no interpolation will be performed. No error will be returned.
|
|
||||||
*/
|
|
||||||
func Interpolate[T any](s T, opts ...optInterpolate) (err error) {
|
|
||||||
|
|
||||||
var sVal reflect.Value = reflect.ValueOf(s)
|
|
||||||
var sType reflect.Type = sVal.Type()
|
|
||||||
var kind reflect.Kind = sType.Kind()
|
|
||||||
var ptrVal reflect.Value
|
|
||||||
var ptrType reflect.Type
|
|
||||||
var ptrKind reflect.Kind
|
|
||||||
|
|
||||||
switch kind {
|
|
||||||
case reflect.Ptr:
|
|
||||||
if sVal.IsNil() || sVal.IsZero() || !sVal.IsValid() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ptrVal = sVal.Elem()
|
|
||||||
ptrType = ptrVal.Type()
|
|
||||||
ptrKind = ptrType.Kind()
|
|
||||||
if ptrKind == reflect.String {
|
|
||||||
err = interpolateStringReflect(ptrVal, opts, nil)
|
|
||||||
} else {
|
|
||||||
// Otherwise, it should be a struct ptr.
|
|
||||||
if ptrKind != reflect.Struct {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = interpolateStruct(ptrVal, opts, nil)
|
|
||||||
}
|
|
||||||
case reflect.Map:
|
|
||||||
if sVal.IsNil() || sVal.IsZero() || !sVal.IsValid() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = interpolateMap(sVal, opts, nil)
|
|
||||||
case reflect.Slice:
|
|
||||||
if sVal.IsNil() || sVal.IsZero() || !sVal.IsValid() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = interpolateSlice(sVal, opts, nil)
|
|
||||||
/*
|
|
||||||
case reflect.Struct:
|
|
||||||
if sVal.IsZero() || !sVal.IsValid() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = interpolateStruct(sVal, opts, nil)
|
|
||||||
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
InterpolateString takes (a pointer to) a struct or string and performs variable substitution on it
|
|
||||||
from environment variables.
|
|
||||||
|
|
||||||
It supports both UNIX/Linux/POSIX syntax formats (e.g. $VARNAME, ${VARNAME}) and,
|
|
||||||
if on Windows, it *additionally* supports the EXPAND_SZ format (e.g. %VARNAME%).
|
|
||||||
|
|
||||||
If s is nil, nothing will be done and err will be ErrNilPtr.
|
|
||||||
|
|
||||||
This is a standalone function that is much more performant than Interpolate
|
|
||||||
at the cost of rigidity.
|
|
||||||
*/
|
|
||||||
func InterpolateString(s *string) (err error) {
|
|
||||||
|
|
||||||
var newStr string
|
|
||||||
|
|
||||||
if s == nil {
|
|
||||||
err = errs.ErrNilPtr
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if newStr, err = interpolateString(*s); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
*s = newStr
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
PopulateStruct takes (a pointer to) a struct and performs *population* on it.
|
|
||||||
Unlike the InterpolateStruct function, this *completely populates* (or *replaces*)
|
|
||||||
a field's value with the specified environment variable; no *substitution* is performed.
|
|
||||||
|
|
||||||
You can change the tag name used by changing the StructTagPopulate variable in this module;
|
|
||||||
the default is `envpop`.
|
|
||||||
|
|
||||||
Tag value format:
|
|
||||||
<tag>:"<VAR NAME>[,<option>,<option>...]"
|
|
||||||
e.g.
|
|
||||||
envpop:"SOMEVAR"
|
|
||||||
envpop:"OTHERVAR,force"
|
|
||||||
envpop:"OTHERVAR,allow_empty"
|
|
||||||
envpop:"OTHERVAR,force,allow_empty"
|
|
||||||
|
|
||||||
If the tag value is "-", or <VAR NAME> is not provided, the field will be explicitly skipped.
|
|
||||||
(This is the default behavior for struct fields not tagged with `envpop`.)
|
|
||||||
|
|
||||||
Recognized options:
|
|
||||||
|
|
||||||
* force - Existing field values that are non-empty strings or non-nil pointers are normally skipped; this option always replaces them.
|
|
||||||
* allow_empty - Normally no replacement will be performed if the specified variable is undefined/not found.
|
|
||||||
This option allows an empty string to be used instead.
|
|
||||||
Not very useful for string fields, but potentially useful for string pointer fields.
|
|
||||||
|
|
||||||
e.g.:
|
|
||||||
|
|
||||||
struct{
|
|
||||||
// If this is an empty string, it will be replaced with the value of $CWD.
|
|
||||||
CurrentDir string `envpop:"CWD"`
|
|
||||||
// This would only populate with $USER if the pointer is nil.
|
|
||||||
UserName *string `envpop:"USER"`
|
|
||||||
// This will *always* replace the field's value with the value of $DISPLAY,
|
|
||||||
// even if not an empty string.
|
|
||||||
// Note the `force` option.
|
|
||||||
Display string `envpop:"DISPLAY,force"`
|
|
||||||
// Likewise, even if not nil, this field's value would be replaced with the value of $SHELL.
|
|
||||||
Shell *string `envpop:"SHELL,force"`
|
|
||||||
// This field will be untouched if non-nil, otherwise it will be a pointer to an empty string
|
|
||||||
// if FOOBAR is undefined.
|
|
||||||
NonExistentVar *string `envpop:"FOOBAR,allow_empty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
If s is nil, nothing will be done and err will be errs.ErrNilPtr.
|
|
||||||
If s is not a pointer to a struct, nothing will be done and err will be errs.ErrBadType.
|
|
||||||
*/
|
|
||||||
func PopulateStruct[T any](s T) (err error) {
|
|
||||||
|
|
||||||
var structVal reflect.Value
|
|
||||||
var structType reflect.Type
|
|
||||||
var field reflect.StructField
|
|
||||||
var fieldVal reflect.Value
|
|
||||||
var tagVal string
|
|
||||||
var valSplit []string
|
|
||||||
var varNm string
|
|
||||||
var varVal string
|
|
||||||
var optsMap map[string]bool
|
|
||||||
var force bool
|
|
||||||
var allowEmpty bool
|
|
||||||
var defined bool
|
|
||||||
|
|
||||||
if reflect.TypeOf(s).Kind() != reflect.Ptr {
|
|
||||||
err = errs.ErrBadType
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
structVal = reflect.ValueOf(s)
|
|
||||||
if structVal.IsNil() || structVal.IsZero() || !structVal.IsValid() {
|
|
||||||
err = errs.ErrNilPtr
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
structVal = reflect.ValueOf(s).Elem()
|
|
||||||
structType = structVal.Type()
|
|
||||||
|
|
||||||
if structType.Kind() != reflect.Struct {
|
|
||||||
err = errs.ErrBadType
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < structVal.NumField(); i++ {
|
|
||||||
field = structType.Field(i)
|
|
||||||
fieldVal = structVal.Field(i)
|
|
||||||
|
|
||||||
// Skip explicitly skipped or non-tagged fields.
|
|
||||||
tagVal = field.Tag.Get(StructTagPopulate)
|
|
||||||
if tagVal == "" || strings.TrimSpace(tagVal) == "-" || strings.HasPrefix(tagVal, "-,") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
fieldVal = structVal.Field(i)
|
|
||||||
if fieldVal.Kind() != reflect.Ptr && fieldVal.Kind() != reflect.String {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
optsMap = make(map[string]bool)
|
|
||||||
valSplit = strings.Split(tagVal, ",")
|
|
||||||
if valSplit == nil || len(valSplit) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
varNm = valSplit[0]
|
|
||||||
if strings.TrimSpace(varNm) == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if len(valSplit) >= 2 {
|
|
||||||
for _, o := range valSplit[1:] {
|
|
||||||
optsMap[o] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
force = optsMap["force"]
|
|
||||||
allowEmpty = optsMap["allow_empty"]
|
|
||||||
|
|
||||||
// if !force && (!fieldVal.IsNil() && !fieldVal.IsZero()) {
|
|
||||||
if !force && !fieldVal.IsZero() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if fieldVal.Kind() == reflect.Ptr {
|
|
||||||
if field.Type.Elem().Kind() != reflect.String {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !fieldVal.CanSet() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
varVal, defined = os.LookupEnv(varNm)
|
|
||||||
if !defined && !allowEmpty {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
switch fieldVal.Kind() {
|
|
||||||
case reflect.Ptr:
|
|
||||||
fieldVal.Set(reflect.ValueOf(&varVal))
|
|
||||||
case reflect.String:
|
|
||||||
fieldVal.SetString(varVal)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// interpolateMap is used by Interpolate and interpolateReflect for maps. v should be a reflect.Value of a map.
|
|
||||||
func interpolateMap(v reflect.Value, opts []optInterpolate, tagOpts []optInterpolate) (err error) {
|
|
||||||
|
|
||||||
var kVal reflect.Value
|
|
||||||
var vVal reflect.Value
|
|
||||||
var mIter *reflect.MapIter
|
|
||||||
var newMap reflect.Value
|
|
||||||
var wg sync.WaitGroup
|
|
||||||
var numJobs int
|
|
||||||
var errChan chan error
|
|
||||||
var doneChan chan bool = make(chan bool, 1)
|
|
||||||
var mErr *multierr.MultiError = multierr.NewMultiError(nil)
|
|
||||||
var t reflect.Type = v.Type()
|
|
||||||
var kind reflect.Kind = t.Kind()
|
|
||||||
var valOpts *interpolateOpts = new(interpolateOpts)
|
|
||||||
|
|
||||||
if kind != reflect.Map {
|
|
||||||
err = errs.ErrBadType
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if v.IsNil() || v.IsZero() || !v.IsValid() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
*valOpts = defaultInterpolateOpts
|
|
||||||
if opts != nil && len(opts) > 0 {
|
|
||||||
for _, opt := range opts {
|
|
||||||
if err = opt(valOpts); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if tagOpts != nil && len(tagOpts) > 0 {
|
|
||||||
for _, opt := range tagOpts {
|
|
||||||
if err = opt(valOpts); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if valOpts.noMapKey && valOpts.noMapVal {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
numJobs = v.Len()
|
|
||||||
errChan = make(chan error, numJobs)
|
|
||||||
wg.Add(numJobs)
|
|
||||||
|
|
||||||
newMap = reflect.MakeMap(reflect.TypeOf(v.Interface()))
|
|
||||||
|
|
||||||
mIter = v.MapRange()
|
|
||||||
for mIter.Next() {
|
|
||||||
kVal = mIter.Key()
|
|
||||||
vVal = mIter.Value()
|
|
||||||
go func(mapK, mapV reflect.Value) {
|
|
||||||
var mapErr error
|
|
||||||
var newKey reflect.Value
|
|
||||||
var newVal reflect.Value
|
|
||||||
|
|
||||||
defer wg.Done()
|
|
||||||
|
|
||||||
if !valOpts.noMapKey {
|
|
||||||
/*
|
|
||||||
if mapK.Kind() == reflect.String {
|
|
||||||
if mapErr = interpolateStringReflect(mapK, opts, nil); mapErr != nil {
|
|
||||||
errChan <- mapErr
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if mapErr = interpolateValue(mapK, opts, nil); mapErr != nil {
|
|
||||||
errChan <- mapErr
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
newKey = reflect.New(mapK.Type())
|
|
||||||
newKey.Set(mapK)
|
|
||||||
if mapK.Kind() == reflect.String {
|
|
||||||
if mapErr = interpolateStringReflect(newKey, opts, nil); mapErr != nil {
|
|
||||||
errChan <- mapErr
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if mapErr = interpolateValue(newKey, opts, nil); mapErr != nil {
|
|
||||||
errChan <- mapErr
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
newKey = mapK
|
|
||||||
}
|
|
||||||
if !valOpts.noMapVal {
|
|
||||||
/*
|
|
||||||
if mapV.Kind() == reflect.String {
|
|
||||||
if mapErr = interpolateStringReflect(mapV, opts, nil); mapErr != nil {
|
|
||||||
errChan <- mapErr
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if mapErr = interpolateValue(mapV, opts, nil); mapErr != nil {
|
|
||||||
errChan <- mapErr
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
newVal = reflect.New(mapV.Type())
|
|
||||||
newVal.Set(mapV)
|
|
||||||
if mapV.Kind() == reflect.String {
|
|
||||||
if mapErr = interpolateStringReflect(newVal, opts, nil); mapErr != nil {
|
|
||||||
errChan <- mapErr
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if mapErr = interpolateValue(newVal, opts, nil); mapErr != nil {
|
|
||||||
errChan <- mapErr
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
newVal = mapV
|
|
||||||
}
|
|
||||||
newMap.SetMapIndex(reflect.ValueOf(newKey), reflect.ValueOf(newVal))
|
|
||||||
}(kVal, vVal)
|
|
||||||
}
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
wg.Wait()
|
|
||||||
close(errChan)
|
|
||||||
doneChan <- true
|
|
||||||
}()
|
|
||||||
|
|
||||||
<-doneChan
|
|
||||||
|
|
||||||
for i := 0; i < numJobs; i++ {
|
|
||||||
if err = <-errChan; err != nil {
|
|
||||||
mErr.AddError(err)
|
|
||||||
err = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !mErr.IsEmpty() {
|
|
||||||
err = mErr
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
v.Set(newMap)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// interpolateSlice is used by Interpolate and interpolateReflect for slices. v should be a reflect.Value of a slice.
|
|
||||||
func interpolateSlice(v reflect.Value, opts []optInterpolate, tagOpts []optInterpolate) (err error) {
|
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
|
||||||
var errChan chan error
|
|
||||||
var numJobs int
|
|
||||||
var doneChan chan bool = make(chan bool, 1)
|
|
||||||
var mErr *multierr.MultiError = multierr.NewMultiError(nil)
|
|
||||||
var t reflect.Type = v.Type()
|
|
||||||
var kind reflect.Kind = t.Kind()
|
|
||||||
var valOpts *interpolateOpts = new(interpolateOpts)
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
if kind != reflect.Slice {
|
|
||||||
err = errs.ErrBadType
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if v.IsNil() || v.IsZero() || !v.IsValid() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
*valOpts = defaultInterpolateOpts
|
|
||||||
if opts != nil && len(opts) > 0 {
|
|
||||||
for _, opt := range opts {
|
|
||||||
if err = opt(valOpts); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
numJobs = v.Len()
|
|
||||||
errChan = make(chan error, numJobs)
|
|
||||||
wg.Add(numJobs)
|
|
||||||
|
|
||||||
for i := 0; i < v.Len(); i++ {
|
|
||||||
go func(idx int) {
|
|
||||||
var sErr error
|
|
||||||
var newVal reflect.Value
|
|
||||||
|
|
||||||
defer wg.Done()
|
|
||||||
|
|
||||||
newVal = reflect.New(v.Index(idx).Type())
|
|
||||||
newVal.Set(v.Index(idx))
|
|
||||||
if v.Index(idx).Kind() == reflect.String {
|
|
||||||
if sErr = interpolateStringReflect(newVal, opts, tagOpts); sErr != nil {
|
|
||||||
errChan <- sErr
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if sErr = interpolateValue(newVal, opts, tagOpts); sErr != nil {
|
|
||||||
errChan <- sErr
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
v.Index(idx).Set(reflect.ValueOf(newVal))
|
|
||||||
}(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
wg.Wait()
|
|
||||||
close(errChan)
|
|
||||||
doneChan <- true
|
|
||||||
}()
|
|
||||||
|
|
||||||
<-doneChan
|
|
||||||
|
|
||||||
for i := 0; i < numJobs; i++ {
|
|
||||||
if err = <-errChan; err != nil {
|
|
||||||
mErr.AddError(err)
|
|
||||||
err = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !mErr.IsEmpty() {
|
|
||||||
err = mErr
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// interpolateStringReflect is used for structs/nested strings using reflection.
|
|
||||||
func interpolateStringReflect(v reflect.Value, opts []optInterpolate, tagOpts []optInterpolate) (err error) {
|
|
||||||
|
|
||||||
var strVal string
|
|
||||||
|
|
||||||
if strVal, err = interpolateString(v.String()); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
v.Set(reflect.ValueOf(strVal).Convert(v.Type()))
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// interpolateStruct is used by Interpolate and interpolateReflect for structs. v should be a reflect.Value of a struct.
|
|
||||||
func interpolateStruct(v reflect.Value, opts []optInterpolate, tagOpts []optInterpolate) (err error) {
|
|
||||||
|
|
||||||
var field reflect.StructField
|
|
||||||
var fieldVal reflect.Value
|
|
||||||
var wg sync.WaitGroup
|
|
||||||
var errChan chan error
|
|
||||||
var numJobs int
|
|
||||||
var doneChan chan bool = make(chan bool, 1)
|
|
||||||
var mErr *multierr.MultiError = multierr.NewMultiError(nil)
|
|
||||||
var t reflect.Type = v.Type()
|
|
||||||
var kind reflect.Kind = t.Kind()
|
|
||||||
|
|
||||||
if kind != reflect.Struct {
|
|
||||||
err = errs.ErrBadType
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
numJobs = v.NumField()
|
|
||||||
wg.Add(numJobs)
|
|
||||||
errChan = make(chan error, numJobs)
|
|
||||||
|
|
||||||
for i := 0; i < v.NumField(); i++ {
|
|
||||||
field = t.Field(i)
|
|
||||||
fieldVal = v.Field(i)
|
|
||||||
|
|
||||||
go func(f reflect.StructField, fv reflect.Value) {
|
|
||||||
var fErr error
|
|
||||||
|
|
||||||
defer wg.Done()
|
|
||||||
|
|
||||||
if fErr = interpolateStructField(f, fv, opts, nil); fErr != nil {
|
|
||||||
errChan <- fErr
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}(field, fieldVal)
|
|
||||||
}
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
wg.Wait()
|
|
||||||
close(errChan)
|
|
||||||
doneChan <- true
|
|
||||||
}()
|
|
||||||
|
|
||||||
<-doneChan
|
|
||||||
|
|
||||||
for i := 0; i < numJobs; i++ {
|
|
||||||
if err = <-errChan; err != nil {
|
|
||||||
mErr.AddError(err)
|
|
||||||
err = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !mErr.IsEmpty() {
|
|
||||||
err = mErr
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// interpolateStructField interpolates a struct field.
|
|
||||||
func interpolateStructField(field reflect.StructField, v reflect.Value, opts []optInterpolate, tagOpts []optInterpolate) (err error) {
|
|
||||||
|
|
||||||
var tagVal string
|
|
||||||
// var ftKind reflect.Kind = field.Type.Kind()
|
|
||||||
var parsedTagOpts map[string]bool
|
|
||||||
var valOpts *interpolateOpts = new(interpolateOpts)
|
|
||||||
|
|
||||||
if !v.CanSet() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
*valOpts = defaultInterpolateOpts
|
|
||||||
|
|
||||||
// Skip if explicitly instructed to do so.
|
|
||||||
tagVal = field.Tag.Get(StructTagInterpolate)
|
|
||||||
parsedTagOpts = internal.StringToMapBool(tagVal)
|
|
||||||
if parsedTagOpts["-"] {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if opts != nil && len(opts) > 0 {
|
|
||||||
for _, opt := range opts {
|
|
||||||
if err = opt(valOpts); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if v.Kind() == reflect.Ptr {
|
|
||||||
err = interpolateStructField(field, v.Elem(), opts, tagOpts)
|
|
||||||
} else {
|
|
||||||
err = interpolateValue(v, opts, tagOpts)
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// interpolateValue is a dispatcher for a reflect value.
|
|
||||||
func interpolateValue(v reflect.Value, opts []optInterpolate, tagOpts []optInterpolate) (err error) {
|
|
||||||
|
|
||||||
var kind reflect.Kind = v.Kind()
|
|
||||||
|
|
||||||
switch kind {
|
|
||||||
case reflect.Ptr:
|
|
||||||
if v.IsNil() || v.IsZero() || !v.IsValid() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
v = v.Elem()
|
|
||||||
if err = interpolateValue(v, opts, tagOpts); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
case reflect.String:
|
|
||||||
if err = interpolateStringReflect(v, opts, tagOpts); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return
|
|
||||||
case reflect.Slice:
|
|
||||||
if err = interpolateSlice(v, opts, tagOpts); err != nil {
|
|
||||||
}
|
|
||||||
case reflect.Map:
|
|
||||||
if err = interpolateMap(v, opts, tagOpts); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
case reflect.Struct:
|
|
||||||
if err = interpolateStruct(v, opts, tagOpts); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
@ -1,33 +1,32 @@
|
|||||||
package envs
|
package envs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
`errors`
|
|
||||||
`os`
|
`os`
|
||||||
`testing`
|
`testing`
|
||||||
`time`
|
`time`
|
||||||
|
|
||||||
`github.com/davecgh/go-spew/spew`
|
`github.com/davecgh/go-spew/spew`
|
||||||
`r00t2.io/sysutils/errs`
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
testCustom string
|
testCustom string
|
||||||
testStruct struct {
|
testStruct struct {
|
||||||
Hello string `envpop:"USER"`
|
Hello string
|
||||||
HelloPtr *string `envpop:"USER"`
|
HelloPtr *string
|
||||||
HelloForce string `envpop:"USER,force"`
|
HelloForce string
|
||||||
HelloPtrForce *string `envpop:"USER,force"`
|
HelloPtrForce *string
|
||||||
HelloNo string `envsub:"-" envpop:"-"`
|
HelloNo string `envsub:"-" envpop:"-"`
|
||||||
HelloNoPtr *string `envsub:"-" envpop:"-"`
|
HelloNoPtr *string `envsub:"-" envpop:"-"`
|
||||||
BadType int
|
BadType int
|
||||||
NilField *string `envpop:"NONEXISTENTBADVAR,allow_empty"`
|
NilField *string
|
||||||
|
NilField2 *string
|
||||||
PtrInt *int
|
PtrInt *int
|
||||||
Custom testCustom
|
Custom testCustom
|
||||||
MapStr map[string]string
|
MapStr map[string]string
|
||||||
SliceStr []string
|
SliceStr []string
|
||||||
SliceSlice [][]string
|
SliceSlice [][]string
|
||||||
SliceMap []map[string]string
|
SliceMap []map[string]string
|
||||||
SliceStruct []testStruct
|
SliceStruct []*testStruct
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -55,41 +54,6 @@ func TestInterpolateStruct(t *testing.T) {
|
|||||||
for _, i := range []interface{}{
|
for _, i := range []interface{}{
|
||||||
"i am ${USER}, it is ${CURDATETIME}",
|
"i am ${USER}, it is ${CURDATETIME}",
|
||||||
new(string),
|
new(string),
|
||||||
/*
|
|
||||||
testStruct{
|
|
||||||
Hello: "i am ${USER}, it is ${CURDATETIME}",
|
|
||||||
HelloPtr: new(string),
|
|
||||||
HelloForce: "i am ${USER}, it is ${CURDATETIME}",
|
|
||||||
HelloPtrForce: new(string),
|
|
||||||
HelloNo: "i am ${USER}, it is ${CURDATETIME}",
|
|
||||||
HelloNoPtr: new(string),
|
|
||||||
BadType: 4,
|
|
||||||
NilField: nil,
|
|
||||||
PtrInt: new(int),
|
|
||||||
Custom: testCustom("i am ${USER}, it is ${CURDATETIME}"),
|
|
||||||
SliceStr: []string{"i am ${USER}, it is ${CURDATETIME}"},
|
|
||||||
SliceSlice: [][]string{[]string{"i am ${USER}, it is ${CURDATETIME}"}},
|
|
||||||
SliceMap: []map[string]string{map[string]string{"i am ${USER} key": "i am ${USER} value, it is ${CURDATETIME}"}},
|
|
||||||
SliceStruct: []testStruct{
|
|
||||||
{
|
|
||||||
Hello: "i am nested ${USER}, it is ${CURDATETIME}",
|
|
||||||
HelloPtr: nil,
|
|
||||||
HelloForce: "i am nested ${USER}, it is ${CURDATETIME}",
|
|
||||||
HelloPtrForce: nil,
|
|
||||||
HelloNo: "i am nested ${USER}, it is ${CURDATETIME}",
|
|
||||||
HelloNoPtr: nil,
|
|
||||||
BadType: 0,
|
|
||||||
NilField: nil,
|
|
||||||
PtrInt: nil,
|
|
||||||
Custom: testCustom("i am nested ${USER}, it is ${CURDATETIME}"),
|
|
||||||
SliceStr: []string{"i am nested ${USER}, it is ${CURDATETIME}"},
|
|
||||||
SliceSlice: [][]string{[]string{"i am nested ${USER}, it is ${CURDATETIME}"}},
|
|
||||||
SliceMap: []map[string]string{map[string]string{"i am nested ${USER} key": "i am ${USER} value, it is ${CURDATETIME}"}},
|
|
||||||
SliceStruct: nil,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
*/
|
|
||||||
&testStruct{
|
&testStruct{
|
||||||
Hello: "i am ${USER}, it is ${CURDATETIME}",
|
Hello: "i am ${USER}, it is ${CURDATETIME}",
|
||||||
HelloPtr: new(string),
|
HelloPtr: new(string),
|
||||||
@ -105,8 +69,8 @@ func TestInterpolateStruct(t *testing.T) {
|
|||||||
SliceStr: []string{"i am ${USER}, it is ${CURDATETIME}"},
|
SliceStr: []string{"i am ${USER}, it is ${CURDATETIME}"},
|
||||||
SliceSlice: [][]string{[]string{"i am ${USER}, it is ${CURDATETIME}"}},
|
SliceSlice: [][]string{[]string{"i am ${USER}, it is ${CURDATETIME}"}},
|
||||||
SliceMap: []map[string]string{map[string]string{"i am ${USER} key": "i am ${USER} value, it is ${CURDATETIME}"}},
|
SliceMap: []map[string]string{map[string]string{"i am ${USER} key": "i am ${USER} value, it is ${CURDATETIME}"}},
|
||||||
SliceStruct: []testStruct{
|
SliceStruct: []*testStruct{
|
||||||
{
|
&testStruct{
|
||||||
Hello: "i am nested ${USER}, it is ${CURDATETIME}",
|
Hello: "i am nested ${USER}, it is ${CURDATETIME}",
|
||||||
HelloPtr: nil,
|
HelloPtr: nil,
|
||||||
HelloForce: "i am nested ${USER}, it is ${CURDATETIME}",
|
HelloForce: "i am nested ${USER}, it is ${CURDATETIME}",
|
||||||
@ -149,34 +113,3 @@ func TestInterpolateStruct(t *testing.T) {
|
|||||||
t.Logf("After (%T):\n%v\n", i, spew.Sdump(i))
|
t.Logf("After (%T):\n%v\n", i, spew.Sdump(i))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPopulateStruct(t *testing.T) {
|
|
||||||
|
|
||||||
var err error
|
|
||||||
var greet string = "My username is ${USER}; hello!"
|
|
||||||
var num int = 4
|
|
||||||
var sp *testStruct = &testStruct{
|
|
||||||
Hello: greet,
|
|
||||||
HelloPtr: &greet,
|
|
||||||
HelloForce: greet,
|
|
||||||
HelloPtrForce: &greet,
|
|
||||||
HelloNo: greet,
|
|
||||||
HelloNoPtr: &greet,
|
|
||||||
BadType: 4,
|
|
||||||
PtrInt: &num,
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = PopulateStruct(sp); err != nil {
|
|
||||||
if errors.Is(err, errs.ErrNilPtr) {
|
|
||||||
err = nil
|
|
||||||
t.Logf("Detected nil.")
|
|
||||||
} else if errors.Is(err, errs.ErrBadType) {
|
|
||||||
err = nil
|
|
||||||
t.Log("Detected bad type.")
|
|
||||||
} else {
|
|
||||||
t.Fatalf("Failed interpolation: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
t.Logf("Evaluated:\n%v", spew.Sdump(sp))
|
|
||||||
|
|
||||||
}
|
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
package envs
|
|
||||||
|
|
||||||
type (
|
|
||||||
interpolateOpts struct {
|
|
||||||
noMapKey bool
|
|
||||||
noMapVal bool
|
|
||||||
isTagged bool
|
|
||||||
}
|
|
||||||
optInterpolate func(o *interpolateOpts) (err error)
|
|
||||||
)
|
|
2
exec_extra/TODO
Normal file
2
exec_extra/TODO
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
- for GetCmdFromStruct, support []byte fields
|
||||||
|
-- support hex and base64 struct field opts (and others?) via `enc=` struct tag.
|
@ -1,34 +1,123 @@
|
|||||||
package exec_extra
|
package exec_extra
|
||||||
|
|
||||||
var (
|
import (
|
||||||
StructTagCmdArgs string = "cmdarg"
|
`r00t2.io/goutils/bitmask`
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
CmdArgsTag string = "cmdarg"
|
||||||
/*
|
/*
|
||||||
CmdArgsOptPreferShort, if specified, prefers the "short" argument over "long" if both are specified.
|
CmdArgsDictSep specifies the string to use to separate keys and values.
|
||||||
The default is to prefer long.
|
|
||||||
|
|
||||||
Can be specified per-field via the `prefer_short` option (no value/value ignored).
|
To override at the struct field level, use the tag value:
|
||||||
|
|
||||||
|
`<CmdArgsTag>:"dictsep=<str>"`
|
||||||
|
|
||||||
|
Where str is the string to use. e.g.:
|
||||||
|
|
||||||
|
`cmdarg:"short=d,long=data,dictsep=."`
|
||||||
|
|
||||||
|
Would render a map value of map[string]string{"foo": "bar"} as:
|
||||||
|
|
||||||
|
`-d foo.bar`
|
||||||
*/
|
*/
|
||||||
CmdArgsOptPreferShort cmdArgOpt = func(opts *cmdArgsOpts) (err error) {
|
CmdArgsDictSep string = ":"
|
||||||
opts.preferShort = true
|
)
|
||||||
return
|
|
||||||
}
|
// CmdArgOptNone is an "empty option" and does nothing.
|
||||||
|
const CmdArgOptNone bitmask.MaskBit = 0
|
||||||
/*
|
const (
|
||||||
CmdArgsOptShortEquals, if specified, renders short flags *with* an equals sign
|
/*
|
||||||
(if using POSIX args).
|
CmdArgOptPreferShort prefers short options where possible.
|
||||||
|
Has no effect if Windows traditional syntax is used.
|
||||||
Has no effect if using Windows traditional syntax or if there is no value for the field.
|
|
||||||
*/
|
The default is to use long options.
|
||||||
CmdArgsOptShortEquals cmdArgOpt = func(opts *cmdArgsOpts) (err error) {
|
See also CmdArgOptPreferLong.
|
||||||
opts.preferShort = true
|
|
||||||
return
|
Corresponding struct tag option: prefer_short
|
||||||
}
|
*/
|
||||||
|
CmdArgOptPreferShort cmdArgOpt = 1 << iota
|
||||||
CmdArgsOptLongNoEquals cmdArgOpt = func(opts *cmdArgsOpts) (err error) {
|
/*
|
||||||
opts.preferShort = true
|
CmdArgOptPreferLong prefers long options where possible.
|
||||||
return
|
Has no effect if Windows traditional syntax is used.
|
||||||
}
|
|
||||||
|
This behavior is the default, but it can be used to
|
||||||
|
override a CmdArgOptPreferShort from a parent.
|
||||||
|
|
||||||
|
Corresponding struct tag option: prefer_long
|
||||||
|
*/
|
||||||
|
CmdArgOptPreferLong
|
||||||
|
/*
|
||||||
|
CmdArgOptShortEquals will use an equals separator
|
||||||
|
for short flags instead of a space (the default).
|
||||||
|
Has no effect if Windows traditional syntax is used.
|
||||||
|
|
||||||
|
Corresponding struct tag option: short_equals
|
||||||
|
*/
|
||||||
|
CmdArgOptShortEquals
|
||||||
|
/*
|
||||||
|
CmdArgOptShortNoEquals will use a space separator
|
||||||
|
for short flags instead of an equals.
|
||||||
|
Has no effect if Windows traditional syntax is used.
|
||||||
|
|
||||||
|
This behavior is the default, but it can be used to
|
||||||
|
override a CmdArgOptPreferShort from a parent.
|
||||||
|
|
||||||
|
Corresponding struct tag option: no_short_equals
|
||||||
|
*/
|
||||||
|
CmdArgOptShortNoEquals
|
||||||
|
/*
|
||||||
|
CmdArgOptLongEquals will use an equals separator
|
||||||
|
for long flags instead of a space.
|
||||||
|
Has no effect if Windows traditional syntax is used.
|
||||||
|
|
||||||
|
This behavior is the default, but it can be used to
|
||||||
|
override a CmdArgOptLongNoEquals from a parent.
|
||||||
|
|
||||||
|
Corresponding struct tag option: long_equals
|
||||||
|
*/
|
||||||
|
CmdArgOptLongEquals
|
||||||
|
/*
|
||||||
|
CmdArgOptLongNoEquals will use a space separator
|
||||||
|
for short flags instead of an equals.
|
||||||
|
Has no effect if Windows traditional syntax is used.
|
||||||
|
|
||||||
|
This behavior is the default, but it can be used to
|
||||||
|
override a CmdArgOptPreferShort from a parent.
|
||||||
|
|
||||||
|
Corresponding struct tag option: no_long_equals
|
||||||
|
*/
|
||||||
|
CmdArgOptLongNoEquals
|
||||||
|
/*
|
||||||
|
CmdArgOptForceNoPosix forces the resulting command string to use "traditional Windows" flag notation.
|
||||||
|
|
||||||
|
Traditionally, Windows used flags like `/f` instead of POSIX `-f`, `/c:value` instead of `-c value`
|
||||||
|
or `-c=value`, etc.
|
||||||
|
Has no effect if not running on Windows.
|
||||||
|
|
||||||
|
This behavior is the default, but it can be used to
|
||||||
|
override a CmdArgOptPreferShort from a parent.
|
||||||
|
|
||||||
|
See also the inverse of this option, CmdArgOptForcePosix.
|
||||||
|
|
||||||
|
Corresponding struct tag option: force_no_posix
|
||||||
|
*/
|
||||||
|
CmdArgOptForceNoPosix
|
||||||
|
/*
|
||||||
|
CmdArgOptForcePosix forces the resulting command string to use "POSIX" flag notation.
|
||||||
|
|
||||||
|
Traditionally, Windows used flags like `/f` instead of POSIX `-f`, `/c:value` instead of `-c value`
|
||||||
|
or `-c=value`, etc.
|
||||||
|
|
||||||
|
If this option is passed, then the POSIX flag syntax (-a/--arg) will be used instead.
|
||||||
|
|
||||||
|
Note that on Windows runtime, the default is to use the traditional slash-based syntax.
|
||||||
|
If you are generating command strings for Powershell or third-party software, you probably
|
||||||
|
want to use CmdArgsOptForcePosix instead.
|
||||||
|
|
||||||
|
See also the inverse of this option, CmdArgsOptForceNoPosix.
|
||||||
|
|
||||||
|
Corresponding struct tag option: force_posix
|
||||||
|
*/
|
||||||
|
CmdArgOptForcePosix
|
||||||
)
|
)
|
||||||
|
@ -1,45 +0,0 @@
|
|||||||
package exec_extra
|
|
||||||
|
|
||||||
var (
|
|
||||||
/*
|
|
||||||
CmdArgsOptForcePosix forces the resulting command string to use "POSIX-style" flag notation.
|
|
||||||
|
|
||||||
Traditionally, Windows used flags like `/f` instead of POSIX `-f`, `/c:value` instead of `-c value`
|
|
||||||
or `-c=value`, etc.
|
|
||||||
|
|
||||||
If this option is passed, either to GetCmdFromStruct() or for a specific field via the
|
|
||||||
tag defined by StructTagCmdArgs (option `force_posix`, no value/value ignored), then the
|
|
||||||
POSIX-style flag syntax will be used instead.
|
|
||||||
|
|
||||||
Note that on Windows runtime, the default is to use the traditional slash-based syntax.
|
|
||||||
If you are generating command strings for Powershell or third-party software, you probably
|
|
||||||
want to use this option.
|
|
||||||
|
|
||||||
See also the inverse of this option, CmdArgsOptForceNoPosix.
|
|
||||||
*/
|
|
||||||
CmdArgsOptForcePosix cmdArgOpt = func(opts *cmdArgsOpts) (err error) {
|
|
||||||
opts.forcePosix = true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
CmdArgsOptForceNoPosix forces the resulting command string to use "traditional Windows" flag notation.
|
|
||||||
|
|
||||||
Traditionally, Windows used flags like `/f` instead of POSIX `-f`, `/c:value` instead of `-c value`
|
|
||||||
or `-c=value`, etc.
|
|
||||||
|
|
||||||
If this option is passed, either to GetCmdFromStruct() or for a specific field via the
|
|
||||||
tag defined by StructTagCmdArgs (option `force_no_posix`, no value/value ignored), then the
|
|
||||||
Windows-style flag syntax will be used instead.
|
|
||||||
|
|
||||||
Note that on Windows runtime, the default is to use the traditional slash-based syntax.
|
|
||||||
If you are generating command strings for Powershell or third-party software, you probably
|
|
||||||
want to use CmdArgsOptForcePosix instead.
|
|
||||||
|
|
||||||
See also the inverse of this option, CmdArgsOptForcePosix.
|
|
||||||
*/
|
|
||||||
CmdArgsOptForceNoPosix cmdArgOpt = func(opts *cmdArgsOpts) (err error) {
|
|
||||||
opts.forcePosix = false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
)
|
|
@ -19,9 +19,20 @@
|
|||||||
package exec_extra
|
package exec_extra
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os/exec"
|
`fmt`
|
||||||
|
`os/exec`
|
||||||
|
`reflect`
|
||||||
|
|
||||||
|
`r00t2.io/goutils/bitmask`
|
||||||
|
`r00t2.io/goutils/structutils`
|
||||||
|
`r00t2.io/sysutils/errs`
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
ExecCmdReturn runs cmd and alsom returns the exitStatus.
|
||||||
|
|
||||||
|
A non-zero exit status is not treated as an error.
|
||||||
|
*/
|
||||||
func ExecCmdReturn(cmd *exec.Cmd) (exitStatus int, err error) {
|
func ExecCmdReturn(cmd *exec.Cmd) (exitStatus int, err error) {
|
||||||
// https://stackoverflow.com/a/55055100/733214
|
// https://stackoverflow.com/a/55055100/733214
|
||||||
err = cmd.Run()
|
err = cmd.Run()
|
||||||
@ -31,14 +42,12 @@ func ExecCmdReturn(cmd *exec.Cmd) (exitStatus int, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
GetCmdFromStruct takes (a pointer to) a struct and returns a slice of
|
GetCmdFromStruct takes a pointer to a struct and returns a slice of
|
||||||
strings compatible with os/exec.Cmd.
|
strings compatible with os/exec.Cmd.
|
||||||
|
|
||||||
The tag name used can be changed by setting the StructTagCmdArgs variable in this module;
|
The tag name used can be changed by setting the CmdArgsTag variable in this module;
|
||||||
the default is `cmdarg`.
|
the default is `cmdarg`.
|
||||||
|
|
||||||
If the tag value is "-", the field will be skipped. Any other tag value(s) are ignored.
|
|
||||||
|
|
||||||
Tag value format:
|
Tag value format:
|
||||||
<tag>:"<option>=<value>[,<option>[=<value>],<option>[=<value>]...]"
|
<tag>:"<option>=<value>[,<option>[=<value>],<option>[=<value>]...]"
|
||||||
e.g.
|
e.g.
|
||||||
@ -46,41 +55,301 @@ func ExecCmdReturn(cmd *exec.Cmd) (exitStatus int, err error) {
|
|||||||
cmdarg:"short=l"
|
cmdarg:"short=l"
|
||||||
cmdarg:"long=list"
|
cmdarg:"long=list"
|
||||||
|
|
||||||
If the tag value is "-", or <VAR NAME> is not provided, the field will be explicitly skipped.
|
If the tag value is "-", the field will be explicitly skipped.
|
||||||
(This is the default behavior for struct fields not tagged with `cmdarg`.)
|
(This is the default behavior for struct fields not tagged with `cmdarg`.)
|
||||||
|
If the field is nil, it will be skipped.
|
||||||
|
|
||||||
If a cmdarg tag is specified but has no `short` or `long` option value, the field will be skipped entirely.
|
If a cmdarg tag is specified but has no `short` or `long` option value, the field will be skipped entirely.
|
||||||
If a field's value is nil, it will be skipped.
|
If a field's value is nil, it will be skipped.
|
||||||
Otherwise if a field's value is the zero-value, it will be skipped.
|
Otherwise if a field's value is the zero-value, it will be skipped.
|
||||||
|
|
||||||
Recognized options:
|
Aside from the 'short' and 'long' tag valued-options, see the comment for each CmdArgOpt* constant
|
||||||
|
for their corresponding tag option and the CmdArgs* variables as well for their corresponding tag option.
|
||||||
|
|
||||||
* short - A short flag for the argument
|
Each struct field can be one of the following types:
|
||||||
|
|
||||||
e.g.:
|
* string
|
||||||
|
* *string
|
||||||
|
* slice (with elements of supported types)
|
||||||
|
* array (with elements of supported types)
|
||||||
|
* map (with keys and values of supported types; see the CmdArgsDictSep variable for the separator to use)
|
||||||
|
* struct (with fields of supported types)
|
||||||
|
* int/int8/int16/int32/int64
|
||||||
|
* uint/uint8/uint16/uint32/uint64
|
||||||
|
* float32/float64
|
||||||
|
|
||||||
struct{
|
Struct fields, slice/array elements, etc. are processed in order.
|
||||||
// If this is an empty string, it will be replaced with the value of $CWD.
|
Maps, because ordering is non-deterministic, may have unpredictable ordering.
|
||||||
CurrentDir string `envpop:"CWD"`
|
|
||||||
// This would only populate with $USER if the pointer is nil.
|
|
||||||
UserName *string `envpop:"USER"`
|
|
||||||
// This will *always* replace the field's value with the value of $DISPLAY,
|
|
||||||
// even if not an empty string.
|
|
||||||
// Note the `force` option.
|
|
||||||
Display string `envpop:"DISPLAY,force"`
|
|
||||||
// Likewise, even if not nil, this field's value would be replaced with the value of $SHELL.
|
|
||||||
Shell *string `envpop:"SHELL,force"`
|
|
||||||
// This field will be untouched if non-nil, otherwise it will be a pointer to an empty string
|
|
||||||
// if FOOBAR is undefined.
|
|
||||||
NonExistentVar *string `envpop:"FOOBAR,allow_empty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
If s is nil, nothing will be done and err will be errs.ErrNilPtr.
|
If s is nil, nothing will be done.
|
||||||
If s is not a pointer to a struct, nothing will be done and err will be errs.ErrBadType.
|
If s is not a pointer to a struct, nothing will be done.
|
||||||
*/
|
*/
|
||||||
func GetCmdFromStruct[T any](s T, opts ...cmdArgOpt) (cmdSlice []string, err error) {
|
func GetCmdFromStruct[T any](s T, defaultOpts ...cmdArgOpt) (cmdSlice []string, err error) {
|
||||||
|
|
||||||
// TODO
|
var tmpSlice []string
|
||||||
|
var ptrVal reflect.Value
|
||||||
|
var ptrType reflect.Type
|
||||||
|
var ptrKind reflect.Kind
|
||||||
|
var argFlags *cmdArgFlag
|
||||||
|
var opts *bitmask.MaskBit = bitmask.NewMaskBit()
|
||||||
|
var sVal reflect.Value = reflect.ValueOf(s)
|
||||||
|
var sType reflect.Type = sVal.Type()
|
||||||
|
var kind reflect.Kind = sType.Kind()
|
||||||
|
|
||||||
|
if kind != reflect.Ptr {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if sVal.IsNil() || sVal.IsZero() || !sVal.IsValid() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ptrVal = sVal.Elem()
|
||||||
|
ptrType = ptrVal.Type()
|
||||||
|
ptrKind = ptrType.Kind()
|
||||||
|
|
||||||
|
if ptrKind != reflect.Struct {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpSlice = make([]string, 0)
|
||||||
|
if defaultOpts != nil && len(defaultOpts) != 0 {
|
||||||
|
for _, o := range defaultOpts {
|
||||||
|
opts.AddFlag(o.BitMask())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
argFlags = &cmdArgFlag{
|
||||||
|
defaults: new(bitmask.MaskBit),
|
||||||
|
fieldOpts: new(bitmask.MaskBit),
|
||||||
|
boolMap: nil,
|
||||||
|
strMap: nil,
|
||||||
|
shortFlag: "",
|
||||||
|
longFlag: "",
|
||||||
|
field: nil,
|
||||||
|
value: &ptrVal,
|
||||||
|
argSlice: &tmpSlice,
|
||||||
|
}
|
||||||
|
*argFlags.defaults = *opts
|
||||||
|
*argFlags.fieldOpts = *opts
|
||||||
|
|
||||||
|
err = getCmdStruct(argFlags)
|
||||||
|
|
||||||
|
cmdSlice = tmpSlice
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// getCmdStruct iterates over each field of reflect.Value struct v, and is called by GetCmdFromStruct.
|
||||||
|
func getCmdStruct(argFlags *cmdArgFlag) (err error) {
|
||||||
|
|
||||||
|
var t reflect.Type
|
||||||
|
var kind reflect.Kind
|
||||||
|
var fieldArgFlag *cmdArgFlag
|
||||||
|
|
||||||
|
if argFlags == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if argFlags.value == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t = argFlags.value.Type()
|
||||||
|
kind = t.Kind()
|
||||||
|
|
||||||
|
if kind != reflect.Struct {
|
||||||
|
err = errs.ErrBadType
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < argFlags.value.NumField(); i++ {
|
||||||
|
fieldArgFlag = new(cmdArgFlag)
|
||||||
|
*fieldArgFlag = *argFlags
|
||||||
|
fieldArgFlag.field = new(reflect.StructField)
|
||||||
|
fieldArgFlag.value = new(reflect.Value)
|
||||||
|
*fieldArgFlag.field = t.Field(i)
|
||||||
|
*fieldArgFlag.value = argFlags.value.Field(i)
|
||||||
|
|
||||||
|
if err = getCmdStructField(fieldArgFlag); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// getCmdStructField parses an individual struct field.
|
||||||
|
func getCmdStructField(argFlags *cmdArgFlag) (err error) {
|
||||||
|
|
||||||
|
if argFlags == nil || argFlags.field == nil || argFlags.value == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
argFlags.boolMap = structutils.TagToBoolMap(*argFlags.field, CmdArgsTag, structutils.TagMapTrim)
|
||||||
|
if argFlags.boolMap["-"] {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
argFlags.strMap = structutils.TagToStringMap(*argFlags.field, CmdArgsTag, structutils.TagMapTrim)
|
||||||
|
if argFlags.strMap == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for key, val := range argFlags.strMap {
|
||||||
|
switch key {
|
||||||
|
case "short":
|
||||||
|
argFlags.shortFlag = val
|
||||||
|
case "long":
|
||||||
|
argFlags.longFlag = val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(argFlags.field.Name + ":")
|
||||||
|
fmt.Printf("BEFORE: %d\t%d\n", argFlags.defaults.Value(), argFlags.fieldOpts.Value())
|
||||||
|
argFlags.fieldOpts = parseCmdArgOpts(argFlags.fieldOpts, argFlags.defaults, *argFlags.field)
|
||||||
|
fmt.Printf("AFTER: %d\t%d\n\n", argFlags.defaults.Value(), argFlags.fieldOpts.Value())
|
||||||
|
/*
|
||||||
|
if v.Kind() == reflect.Ptr {
|
||||||
|
if v.IsNil() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = getCmdStructField(field, v.Elem(), current, defaults, tmpSlice)
|
||||||
|
} else {
|
||||||
|
err = getCmdValue(v, opts, tagVals, tmpSlice)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// getCmdValue is a dispatcher for a reflect value.
|
||||||
|
func getCmdValue(v reflect.Value, opts *bitmask.MaskBit, flagVals map[string]string, tmpSlice *[]string) (err error) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
var kind reflect.Kind = v.Kind()
|
||||||
|
|
||||||
|
switch kind {
|
||||||
|
case reflect.Ptr:
|
||||||
|
if v.IsNil() || v.IsZero() || !v.IsValid() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
v = v.Elem()
|
||||||
|
if err = getCmdValue(v, opts, tmpSlice); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case reflect.String:
|
||||||
|
if err = getCmdString(v, opts, tmpSlice); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
case reflect.Slice, reflect.Array:
|
||||||
|
if err = getCmdSlice(v); err != nil {
|
||||||
|
}
|
||||||
|
case reflect.Map:
|
||||||
|
if err = getCmdMap(v); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case reflect.Struct:
|
||||||
|
if err = getCmdStruct(v); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseCmdArgOpts returns a parsed, combined, etc. set of options into a single OR'd bitmask.
|
||||||
|
func parseCmdArgOpts(current *bitmask.MaskBit, defaults *bitmask.MaskBit, field reflect.StructField) (opts *bitmask.MaskBit) {
|
||||||
|
|
||||||
|
var tagOpts *bitmask.MaskBit = tagOptsToMask(field)
|
||||||
|
|
||||||
|
opts = defaults.Copy()
|
||||||
|
fmt.Printf(
|
||||||
|
"PARSE BEFORE:\n\tOPTS:\t%d\n\tCURRENT:\t%d\n\tDEFAULTS:\t%d\n\tTAGOPTS:\t%d\n",
|
||||||
|
opts.Value(),
|
||||||
|
)
|
||||||
|
for _, b := range []*bitmask.MaskBit{
|
||||||
|
current,
|
||||||
|
tagOpts,
|
||||||
|
} {
|
||||||
|
if b == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if b.HasFlag(CmdArgOptPreferShort.BitMask()) && !b.HasFlag(CmdArgOptPreferLong.BitMask()) {
|
||||||
|
opts.AddFlag(CmdArgOptPreferShort.BitMask())
|
||||||
|
opts.ClearFlag(CmdArgOptPreferLong.BitMask())
|
||||||
|
} else {
|
||||||
|
opts.AddFlag(CmdArgOptPreferLong.BitMask())
|
||||||
|
opts.ClearFlag(CmdArgOptPreferShort.BitMask())
|
||||||
|
}
|
||||||
|
if b.HasFlag(CmdArgOptShortEquals.BitMask()) && !b.HasFlag(CmdArgOptShortNoEquals.BitMask()) {
|
||||||
|
opts.AddFlag(CmdArgOptShortEquals.BitMask())
|
||||||
|
opts.ClearFlag(CmdArgOptShortNoEquals.BitMask())
|
||||||
|
} else {
|
||||||
|
opts.AddFlag(CmdArgOptShortNoEquals.BitMask())
|
||||||
|
opts.ClearFlag(CmdArgOptShortEquals.BitMask())
|
||||||
|
}
|
||||||
|
if b.HasFlag(CmdArgOptLongNoEquals.BitMask()) && !b.HasFlag(CmdArgOptLongEquals.BitMask()) {
|
||||||
|
opts.AddFlag(CmdArgOptLongNoEquals.BitMask())
|
||||||
|
opts.ClearFlag(CmdArgOptLongEquals.BitMask())
|
||||||
|
} else {
|
||||||
|
opts.AddFlag(CmdArgOptLongEquals.BitMask())
|
||||||
|
opts.ClearFlag(CmdArgOptLongNoEquals.BitMask())
|
||||||
|
}
|
||||||
|
if b.HasFlag(CmdArgOptForcePosix.BitMask()) && !b.HasFlag(CmdArgOptForceNoPosix.BitMask()) {
|
||||||
|
opts.AddFlag(CmdArgOptForcePosix.BitMask())
|
||||||
|
opts.ClearFlag(CmdArgOptForceNoPosix.BitMask())
|
||||||
|
} else {
|
||||||
|
opts.AddFlag(CmdArgOptForceNoPosix.BitMask())
|
||||||
|
opts.ClearFlag(CmdArgOptForcePosix.BitMask())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Printf("PARSE AFTER: %d\n", opts.Value())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// tagOptsToMask returns a bitmask.MaskBit from a struct field's tags.
|
||||||
|
func tagOptsToMask(field reflect.StructField) (b *bitmask.MaskBit) {
|
||||||
|
|
||||||
|
var o cmdArgOpt
|
||||||
|
var tagOpts map[string]bool = structutils.TagToBoolMap(field, CmdArgsTag, structutils.TagMapTrim)
|
||||||
|
|
||||||
|
b = bitmask.NewMaskBit()
|
||||||
|
|
||||||
|
// First round, these are normally disabled.
|
||||||
|
for k, v := range tagOpts {
|
||||||
|
switch k {
|
||||||
|
case "prefer_short":
|
||||||
|
o = CmdArgOptPreferShort
|
||||||
|
case "short_equals":
|
||||||
|
o = CmdArgOptShortEquals
|
||||||
|
case "no_long_equals":
|
||||||
|
o = CmdArgOptLongNoEquals
|
||||||
|
case "force_posix":
|
||||||
|
o = CmdArgOptForcePosix
|
||||||
|
}
|
||||||
|
if v {
|
||||||
|
b.AddFlag(o.BitMask())
|
||||||
|
} else {
|
||||||
|
b.ClearFlag(o.BitMask())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Second round, these override the above.
|
||||||
|
for k, v := range tagOpts {
|
||||||
|
switch k {
|
||||||
|
case "prefer_long":
|
||||||
|
o = CmdArgOptPreferShort
|
||||||
|
case "no_short_equals":
|
||||||
|
o = CmdArgOptShortEquals
|
||||||
|
case "long_equals":
|
||||||
|
o = CmdArgOptLongNoEquals
|
||||||
|
case "force_no_posix":
|
||||||
|
o = CmdArgOptForcePosix
|
||||||
|
}
|
||||||
|
// Since these are meant to disable, we flip things around.
|
||||||
|
if v {
|
||||||
|
b.ClearFlag(o.BitMask())
|
||||||
|
} else {
|
||||||
|
b.AddFlag(o.BitMask())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
13
exec_extra/funcs_cmdargopt.go
Normal file
13
exec_extra/funcs_cmdargopt.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package exec_extra
|
||||||
|
|
||||||
|
import (
|
||||||
|
`r00t2.io/goutils/bitmask`
|
||||||
|
)
|
||||||
|
|
||||||
|
// BitMask returns the underlying bitmask.MaskBit representation of a cmdArgOpt.
|
||||||
|
func (c cmdArgOpt) BitMask() (b bitmask.MaskBit) {
|
||||||
|
|
||||||
|
b = bitmask.MaskBit(c)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
27
exec_extra/funcs_test.go
Normal file
27
exec_extra/funcs_test.go
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package exec_extra
|
||||||
|
|
||||||
|
import (
|
||||||
|
`testing`
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
testStruct struct {
|
||||||
|
Foo string `cmdarg:"short=f,long=foo"`
|
||||||
|
Bar int `cmdarg:"short=b,long=bar,prefer_short"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetCmdFromStruct(t *testing.T) {
|
||||||
|
|
||||||
|
var err error
|
||||||
|
var out []string
|
||||||
|
var v *testStruct = &testStruct{
|
||||||
|
Foo: "foo",
|
||||||
|
Bar: 123,
|
||||||
|
}
|
||||||
|
|
||||||
|
if out, err = GetCmdFromStruct(v); err != nil {
|
||||||
|
t.Fatalf("Received error getting command from struct: %v", err)
|
||||||
|
}
|
||||||
|
t.Logf("Got command args from struct:\n%#v", out)
|
||||||
|
}
|
@ -1,9 +1,25 @@
|
|||||||
package exec_extra
|
package exec_extra
|
||||||
|
|
||||||
type cmdArgsOpts struct {
|
import (
|
||||||
preferShort bool
|
`reflect`
|
||||||
forcePosix bool
|
|
||||||
cmd *string
|
|
||||||
}
|
|
||||||
|
|
||||||
type cmdArgOpt func(*cmdArgsOpts) (err error)
|
`r00t2.io/goutils/bitmask`
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
cmdArgOpt bitmask.MaskBit
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
cmdArgFlag struct {
|
||||||
|
defaults *bitmask.MaskBit
|
||||||
|
fieldOpts *bitmask.MaskBit
|
||||||
|
boolMap map[string]bool
|
||||||
|
strMap map[string]string
|
||||||
|
shortFlag string
|
||||||
|
longFlag string
|
||||||
|
field *reflect.StructField
|
||||||
|
value *reflect.Value
|
||||||
|
argSlice *[]string
|
||||||
|
}
|
||||||
|
)
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
package exec_extra
|
|
||||||
|
|
||||||
import (
|
|
||||||
`r00t2.io/sysutils/paths`
|
|
||||||
)
|
|
||||||
|
|
||||||
/*
|
|
||||||
CmdArgsWithBin returns a cmdArgsOpt that specifies program/executable/binary path `bin`,
|
|
||||||
ensuring that the resulting cmdSlice from GetCmdFromStruct() will return a ready-to-use slice.
|
|
||||||
(Otherwise the executable would need to be prepended to the resulting slice.)
|
|
||||||
|
|
||||||
Path normalization/canonziation can be enabled/disabled via normalizePath.
|
|
||||||
*/
|
|
||||||
func CmdArgsWithBin(bin string, normalizePath bool) (opt cmdArgOpt, err error) {
|
|
||||||
|
|
||||||
if normalizePath {
|
|
||||||
if err = paths.RealPath(&bin); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
opt = func(opts *cmdArgsOpts) (err error) {
|
|
||||||
/*
|
|
||||||
if opts.cmd == nil {
|
|
||||||
opts.cmd = new(string)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
*opts.cmd = bin
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
8
go.mod
8
go.mod
@ -5,8 +5,14 @@ go 1.21
|
|||||||
require (
|
require (
|
||||||
github.com/davecgh/go-spew v1.1.1
|
github.com/davecgh/go-spew v1.1.1
|
||||||
github.com/g0rbe/go-chattr v1.0.1
|
github.com/g0rbe/go-chattr v1.0.1
|
||||||
|
github.com/google/uuid v1.6.0
|
||||||
golang.org/x/sys v0.19.0
|
golang.org/x/sys v0.19.0
|
||||||
r00t2.io/goutils v1.4.0
|
r00t2.io/goutils v1.6.0
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf // indirect
|
||||||
|
github.com/godbus/dbus v4.1.0+incompatible // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
// Pending https://github.com/g0rbe/go-chattr/pull/3
|
// Pending https://github.com/g0rbe/go-chattr/pull/3
|
||||||
|
10
go.sum
10
go.sum
@ -1,7 +1,13 @@
|
|||||||
|
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU=
|
||||||
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/godbus/dbus v4.1.0+incompatible h1:WqqLRTsQic3apZUK9qC5sGNfXthmPXzUZ7nQPrNITa4=
|
||||||
|
github.com/godbus/dbus v4.1.0+incompatible/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
|
||||||
|
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/johnnybubonic/go-chattr v0.0.0-20240126141003-459f46177b13 h1:tgEbuE4bNVjaCWWIB1u9lDzGqH/ZdBTg33+4vNW2rjg=
|
github.com/johnnybubonic/go-chattr v0.0.0-20240126141003-459f46177b13 h1:tgEbuE4bNVjaCWWIB1u9lDzGqH/ZdBTg33+4vNW2rjg=
|
||||||
github.com/johnnybubonic/go-chattr v0.0.0-20240126141003-459f46177b13/go.mod h1:yQc6VPJfpDDC1g+W2t47+yYmzBNioax/GLiyJ25/IOs=
|
github.com/johnnybubonic/go-chattr v0.0.0-20240126141003-459f46177b13/go.mod h1:yQc6VPJfpDDC1g+W2t47+yYmzBNioax/GLiyJ25/IOs=
|
||||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
@ -9,4 +15,8 @@ golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
|
|||||||
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
r00t2.io/goutils v1.4.0 h1:/x/etLpMFv3+j1aPtT7KK2G0uOk+gQkGvXIYBCdjn3E=
|
r00t2.io/goutils v1.4.0 h1:/x/etLpMFv3+j1aPtT7KK2G0uOk+gQkGvXIYBCdjn3E=
|
||||||
r00t2.io/goutils v1.4.0/go.mod h1:9ObJI9S71wDLTOahwoOPs19DhZVYrOh4LEHmQ8SW4Lk=
|
r00t2.io/goutils v1.4.0/go.mod h1:9ObJI9S71wDLTOahwoOPs19DhZVYrOh4LEHmQ8SW4Lk=
|
||||||
|
r00t2.io/goutils v1.5.0 h1:haVk+wUK1BAk8f4UFGjy3ov3DwGMauZAOv/XYdb9isQ=
|
||||||
|
r00t2.io/goutils v1.5.0/go.mod h1:9ObJI9S71wDLTOahwoOPs19DhZVYrOh4LEHmQ8SW4Lk=
|
||||||
|
r00t2.io/goutils v1.6.0 h1:oBC6PgBv0y/fdHeCmWgORHpBiU8uWw7IfFQJX5rIuzY=
|
||||||
|
r00t2.io/goutils v1.6.0/go.mod h1:9ObJI9S71wDLTOahwoOPs19DhZVYrOh4LEHmQ8SW4Lk=
|
||||||
r00t2.io/sysutils v1.1.1/go.mod h1:Wlfi1rrJpoKBOjWiYM9rw2FaiZqraD6VpXyiHgoDo/o=
|
r00t2.io/sysutils v1.1.1/go.mod h1:Wlfi1rrJpoKBOjWiYM9rw2FaiZqraD6VpXyiHgoDo/o=
|
||||||
|
@ -2,7 +2,6 @@ package internal
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
`runtime`
|
`runtime`
|
||||||
`strings`
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetPathEnvName gets the OS-specific path environment variable name.
|
// GetPathEnvName gets the OS-specific path environment variable name.
|
||||||
@ -17,85 +16,3 @@ func GetPathEnvName() (envVarName string) {
|
|||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
StringToMap takes string s, assumed to be in the form of
|
|
||||||
key=value[,key=value,key=value...]
|
|
||||||
and returns a map[string]string (map[key]value).
|
|
||||||
It is proccessed in order; later duplicate keys overwrite previous ones.
|
|
||||||
|
|
||||||
If s is an empty string or comprised only of whitespace, m will be nil.
|
|
||||||
If only a key is provided with no value, the value in the map will be an empty string.
|
|
||||||
(e.g. "foo,bar=baz" => map[string]string{"foo": "", "bar: "baz"}
|
|
||||||
|
|
||||||
Surrounding whitespace is trimmed.
|
|
||||||
*/
|
|
||||||
func StringToMap(s string) (m map[string]string) {
|
|
||||||
|
|
||||||
var kvSplit []string
|
|
||||||
var valSplit []string
|
|
||||||
var k string
|
|
||||||
var v string
|
|
||||||
|
|
||||||
if strings.TrimSpace(s) == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
kvSplit = strings.Split(s, ",")
|
|
||||||
if kvSplit == nil || len(kvSplit) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for _, kv := range kvSplit {
|
|
||||||
valSplit = strings.SplitN(kv, "=", 2)
|
|
||||||
if valSplit == nil || len(valSplit) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
k = valSplit[0]
|
|
||||||
switch len(valSplit) {
|
|
||||||
case 1:
|
|
||||||
v = ""
|
|
||||||
case 2:
|
|
||||||
v = valSplit[1]
|
|
||||||
// It's not possible to have more than 2.
|
|
||||||
}
|
|
||||||
if m == nil {
|
|
||||||
m = make(map[string]string)
|
|
||||||
}
|
|
||||||
k = strings.TrimSpace(k)
|
|
||||||
v = strings.TrimSpace(v)
|
|
||||||
m[k] = v
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
StringToMapBool is like StringToMap but designed for a map of booleans.
|
|
||||||
It takes string s, assumed to be in the form of
|
|
||||||
option[,option,option...]
|
|
||||||
and returns a map[string]bool (map[option]true).
|
|
||||||
|
|
||||||
If s is an empty string or comprised only of whitespace, m will be nil.
|
|
||||||
|
|
||||||
Surrounding whitespace is trimmed.
|
|
||||||
*/
|
|
||||||
func StringToMapBool(s string) (m map[string]bool) {
|
|
||||||
|
|
||||||
var optSplit []string
|
|
||||||
|
|
||||||
if strings.TrimSpace(s) == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
optSplit = strings.Split(s, ",")
|
|
||||||
if optSplit == nil || len(optSplit) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
m = make(map[string]bool)
|
|
||||||
for _, o := range optSplit {
|
|
||||||
o = strings.TrimSpace(o)
|
|
||||||
m[o] = true
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user