cotlib

package module
v0.2.8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 24, 2025 License: MIT Imports: 15 Imported by: 0

README

Cursor On Target

'…we want the target dead or saved…we gotta get away from platform centric thinking…and we gotta focus on this thing where the sum of the wisdom is a cursor over the target…and we're indifferent [to the source]' — Gen. John Jumper

CoT Library

Go Report Card

A comprehensive Go library for creating, validating, and working with Cursor-on-Target (CoT) events.

Features

  • High-performance processing: Sub-microsecond event creation, millions of validations/sec
  • Complete CoT event creation and manipulation
  • XML serialization and deserialization with security protections
  • Full CoT type catalog with metadata
  • Zero-allocation type lookups and optimized memory usage
  • How and relation value support with comprehensive validation
  • Coordinate and spatial data handling
  • Event relationship management
  • Type validation and registration
  • Secure logging with slog
  • Thread-safe operations
  • Detail extensions with round-trip preservation
  • Predicate-based event classification
  • Security-first design
  • Wildcard pattern support for types
  • Type search by description or full name

Installation

go get github.com/NERVsystems/cotlib

Usage

Creating and Managing CoT Events
package main

import (
    "fmt"
    "log/slog"
    "os"
    "github.com/NERVsystems/cotlib"
)

func main() {
    logger := slog.New(slog.NewTextHandler(os.Stdout, nil))

    // Create a new CoT event
    event, err := cotlib.NewEvent("UNIT-123", "a-f-G", 37.422, -122.084, 0.0)
    if err != nil {
        logger.Error("Failed to create event", "error", err)
        return
    }

    // Add detail information
    event.Detail = &cotlib.Detail{
        Contact: &cotlib.Contact{
            Callsign: "ALPHA-7",
        },
        Group: &cotlib.Group{
            Name: "Team Blue",
            Role: "Infantry",
        },
    }

    // Add relationship link
    event.AddLink(&cotlib.Link{
        Uid:      "HQ-1",
        Type:     "a-f-G-U-C",
        Relation: "p-p",
    })

    // Convert to XML
    xmlData, err := event.ToXML()
    if err != nil {
        logger.Error("Failed to convert to XML", "error", err)
        return
    }

    fmt.Println(string(xmlData))
}
Parsing CoT XML
package main

import (
    "fmt"
    "github.com/NERVsystems/cotlib"
)

func main() {
    xmlData := `<?xml version="1.0" encoding="UTF-8"?>
<event version="2.0" uid="UNIT-123" type="a-f-G" time="2023-05-15T18:30:22Z"
       start="2023-05-15T18:30:22Z" stale="2023-05-15T18:30:32Z">
  <point lat="37.422000" lon="-122.084000" hae="0.0" ce="9999999.0" le="9999999.0"/>
  <detail>
    <contact callsign="ALPHA-7"/>
    <group name="Team Blue" role="Infantry"/>
  </detail>
</event>`

    // Parse XML into CoT event
    event, err := cotlib.UnmarshalXMLEvent([]byte(xmlData))
    if err != nil {
        fmt.Printf("Error parsing XML: %v\n", err)
        return
    }

    // Access event data
    fmt.Printf("Event Type: %s\n", event.Type)
    fmt.Printf("Location: %.6f, %.6f\n", event.Point.Lat, event.Point.Lon)
    fmt.Printf("Callsign: %s\n", event.Detail.Contact.Callsign)

    // Check event predicates
    if event.Is("friend") {
        fmt.Println("This is a friendly unit")
    }

    if event.Is("ground") {
        fmt.Println("This is a ground-based entity")
    }
}
Handling Detail Extensions

CoT events often include TAK-specific extensions inside the <detail> element. cotlib now preserves several common extensions and round-trips them unchanged:

  • __chat
  • __chatReceipt
  • __geofence
  • __serverdestination
  • __video
  • __group
  • archive
  • attachmentList
  • environment
  • fileshare
  • precisionlocation
  • takv
  • track
  • mission
  • status
  • shape

Example: adding a shape extension with a strokeColor attribute:

event.Detail = &cotlib.Detail{
    Shape: &cotlib.Shape{Raw: []byte(`<shape strokeColor="#00FF00"/>`)},
}

Any unknown elements are stored in Detail.Unknown and serialized back verbatim.

xmlData := `<?xml version="1.0"?>
<event version="2.0" uid="EXT-1" type="t-x-c" time="2023-05-15T18:30:22Z" start="2023-05-15T18:30:22Z" stale="2023-05-15T18:30:32Z">
  <point lat="0" lon="0" ce="9999999.0" le="9999999.0"/>
  <detail>
    <__chat message="Hello world!" sender="Alpha"/>
    <__video url="http://example/video"/>
  </detail>
</event>`

evt, _ := cotlib.UnmarshalXMLEvent([]byte(xmlData))
out, _ := evt.ToXML()
fmt.Println(string(out)) // prints the same XML
Type Validation and Catalog

The library provides comprehensive type validation and catalog management:

package main

import (
    "fmt"
    "log"
    "github.com/NERVsystems/cotlib"
)

func main() {
    // Register a custom CoT type
    if err := cotlib.RegisterCoTType("a-f-G-U-C-F"); err != nil {
        log.Fatal(err)
    }

    // Validate a CoT type
    if err := cotlib.ValidateType("a-f-G-U-C-F"); err != nil {
        log.Fatal(err)
    }

    // Look up type metadata
    fullName, err := cotlib.GetTypeFullName("a-f-G-E-X-N")
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("Full name: %s\n", fullName)
    // Output: Full name: Gnd/Equip/Nbc Equipment

    // Get type description
    desc, err := cotlib.GetTypeDescription("a-f-G-E-X-N")
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("Description: %s\n", desc)
    // Output: Description: NBC EQUIPMENT

    // Search for types by description
    types := cotlib.FindTypesByDescription("NBC")
    for _, t := range types {
        fmt.Printf("Found type: %s (%s)\n", t.Name, t.Description)
    }

    // Search for types by full name
    types = cotlib.FindTypesByFullName("Equipment")
    for _, t := range types {
        fmt.Printf("Found type: %s (%s)\n", t.Name, t.FullName)
    }
}

catalog.Upsert precomputes upper-case versions of each type's FullName and Description. FindByDescription and FindByFullName reuse these cached strings so searches are allocation-free.

Type Validation

The library enforces strict validation of CoT types:

  • Basic syntax checking
  • Standard prefix validation
  • Length limits
  • Wildcard pattern validation
  • Type catalog verification
// Examples of different validation scenarios:
cotlib.ValidateType("a-f-G")             // Valid - Friendly Ground
cotlib.ValidateType("b-m-r")             // Valid - Route
cotlib.ValidateType("invalid")           // Error - Unknown type
How and Relation Values

The library provides full support for CoT how values (indicating position source) and relation values (for event relationships):

How Values

How values indicate the source or method of position determination:

package main

import (
    "fmt"
    "github.com/NERVsystems/cotlib"
)

func main() {
    // Create an event
    event, _ := cotlib.NewEvent("UNIT-123", "a-f-G", 37.422, -122.084, 0.0)
    
    // Set how value using descriptor (recommended)
    err := cotlib.SetEventHowFromDescriptor(event, "gps")
    if err != nil {
        log.Fatal(err)
    }
    // This sets event.How to "h-g-i-g-o"
    
    // Or set directly if you know the code
    event.How = "h-e" // manually entered
    
    // Validate how value
    if err := cotlib.ValidateHow(event.How); err != nil {
        log.Fatal(err)
    }
    
    // Get human-readable description
    desc, _ := cotlib.GetHowDescriptor("h-g-i-g-o")
    fmt.Printf("How: %s\n", desc) // Output: How: gps
}
Relation Values

Relation values specify the relationship type in link elements:

// Add a validated link with parent-point relation
err := event.AddValidatedLink("HQ-1", "a-f-G-U-C", "p-p")
if err != nil {
    log.Fatal(err)
}

// Or add manually (validation happens during event.Validate())
event.AddLink(&cotlib.Link{
    Uid:      "CHILD-1",
    Type:     "a-f-G",
    Relation: "p-c", // parent-child
})

// Get relation description
desc, _ := cotlib.GetRelationDescription("p-p")
fmt.Printf("Relation: %s\n", desc) // Output: Relation: parent-point
Available Values

How values include:

  • h-e (manual entry)
  • h-g-i-g-o (GPS)
  • m-g (GPS - MITRE)
  • And many others from both MITRE and TAK specifications

Relation values include:

  • c (connected)
  • p-p (parent-point)
  • p-c (parent-child)
  • p (parent - MITRE)
  • And many others from both MITRE and TAK specifications
Validation

Event validation automatically checks how and relation values:

event.How = "invalid-how"
err := event.Validate() // Will fail

event.AddLink(&cotlib.Link{
    Uid:      "test",
    Type:     "a-f-G", 
    Relation: "invalid-relation",
})
err = event.Validate() // Will fail
Custom Types

You can register custom type codes that extend the standard prefixes:

// Register a custom type
cotlib.RegisterCoTType("a-f-G-E-V-custom")

// Validate the custom type
if err := cotlib.ValidateType("a-f-G-E-V-custom"); err != nil {
    log.Fatal(err)
}

ctx := cotlib.WithLogger(context.Background(), logger)

// Register types from a file
if err := cotlib.RegisterCoTTypesFromFile(ctx, "my-types.xml"); err != nil {
    log.Fatal(err)
}

// Register types from a string
xmlContent := `<types>
    <cot cot="a-f-G-custom"/>
    <cot cot="a-h-A-custom"/>
</types>`
if err := cotlib.RegisterCoTTypesFromXMLContent(ctx, xmlContent); err != nil {
    log.Fatal(err)
}
Generating Type Metadata (cotgen)

The cmd/cotgen utility expands the CoT XML definitions and writes the cottypes/generated_types.go file used by the library. Ensure the cot-types directory (or your own XML definitions) is present, then run:

go run ./cmd/cotgen
# or simply
go generate ./cottypes

Add your custom type entries to cot-types/CoTtypes.xml before running the generator to embed them into the resulting Go code.

TAK Types and Extensions

The library supports both canonical MITRE CoT types and TAK-specific extensions. TAK types are maintained separately to ensure clear namespace separation and avoid conflicts with official MITRE specifications.

Adding New CoT Types

For MITRE/canonical types: Add entries to cot-types/CoTtypes.xml For TAK-specific types: Add entries to cot-types/TAKtypes.xml

The generator automatically discovers and processes all *.xml files in the cot-types/ directory.

TAK Namespace

All TAK-specific types use the TAK/ namespace prefix in their full attribute to distinguish them from MITRE types:

<!-- TAK-specific types in cot-types/TAKtypes.xml -->
<cot cot="b-t-f" full="TAK/Bits/File" desc="File Transfer" />
<cot cot="u-d-f" full="TAK/Drawing/FreeForm" desc="Free Form Drawing" />
<cot cot="t-x-c" full="TAK/Chat/Message" desc="Chat Message" />
Working with TAK Types
// Check if a type is TAK-specific
typ, err := cottypes.GetCatalog().GetType("b-t-f")
if err != nil {
    log.Fatal(err)
}

if cottypes.IsTAK(typ) {
    fmt.Printf("%s is a TAK type: %s\n", typ.Name, typ.FullName)
    // Output: b-t-f is a TAK type: TAK/Bits/File
}

// Search for TAK types specifically
takTypes := cottypes.GetCatalog().FindByFullName("TAK/")
fmt.Printf("Found %d TAK types\n", len(takTypes))

// Validate TAK types
if err := cotlib.ValidateType("b-t-f"); err != nil {
    log.Fatal(err) // TAK types are fully validated
}
Generator Workflow
  1. The generator scans cot-types/*.xml for type definitions
  2. Parses each XML file into the standard <types><cot> structure
  3. Validates TAK namespace integrity (no a- prefixes with TAK/ full names)
  4. Expands MITRE wildcards (a-.-) but leaves TAK types unchanged
  5. Generates cottypes/generated_types.go with all types
Adding New Types

To add new CoT types to the catalog:

  1. For MITRE types: Edit cot-types/CoTtypes.xml
  2. For TAK extensions: Edit cot-types/TAKtypes.xml
  3. For new categories: Create a new XML file in cot-types/
  4. Run go generate ./cottypes to regenerate the catalog
  5. Verify with tests: go test ./cottypes -v -run TestTAK

Example TAK type entry:

<cot cot="b-m-p-c-z" full="TAK/Map/Zone" desc="Map Zone" />

Important: TAK types should never use the a- prefix (reserved for MITRE affiliation-based types) and must always use the TAK/ namespace prefix.

Event Predicates

The library provides convenient type classification with the Is() method:

// Create a friendly ground unit event
event, _ := cotlib.NewEvent("test123", "a-f-G", 30.0, -85.0, 0.0)

// Check various predicates
fmt.Printf("Is friendly: %v\n", event.Is("friend"))  // true
fmt.Printf("Is hostile: %v\n", event.Is("hostile")) // false
fmt.Printf("Is ground: %v\n", event.Is("ground"))   // true
fmt.Printf("Is air: %v\n", event.Is("air"))         // false
Thread Safety

All operations in the library are thread-safe. The type catalog uses internal synchronization to ensure safe concurrent access.

Security Features

The library implements several security measures:

  • XML parsing restrictions to prevent XXE attacks
  • Input validation on all fields
  • Coordinate range enforcement
  • Time field validation to prevent time-based attacks
  • Maximum value length controls
  • Configurable parser limits
  • UID values are limited to 64 characters and may not contain whitespace
  • Secure logging practices
// Set maximum allowed length for XML attribute values
// This protects against memory exhaustion attacks
cotlib.SetMaxValueLen(500 * 1024) // 500KB limit
cotlib.SetMaxXMLSize(2 << 20)    // 2MB overall XML size
cotlib.SetMaxElementDepth(32)    // nesting depth limit
cotlib.SetMaxElementCount(10000) // total element limit
cotlib.SetMaxTokenLen(1024)      // single token size
Logging

The library uses slog for structured logging:

  • Debug level for detailed operations
  • Info level for normal events
  • Warn level for recoverable issues
  • Error level for critical problems
logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
    Level: slog.LevelDebug,
}))

ctx := cotlib.WithLogger(context.Background(), logger)
log := cotlib.LoggerFromContext(ctx)
log.Info("logger ready")
Event Pooling

UnmarshalXMLEvent reuses Event objects from an internal pool to reduce allocations. When you are done with an event, return it to the pool:

evt, _ := cotlib.UnmarshalXMLEvent(data)
defer cotlib.ReleaseEvent(evt)

Benchmarks

Run benchmarks with the standard Go tooling:

go test -bench=. ./...

This executes any Benchmark... functions across the module, allowing you to profile serialization, validation, or other operations.

Performance

This library is optimized for high-performance CoT processing with minimal memory allocations:

Core Operations (Apple M4)
Operation Speed Allocations Memory Throughput
Event Creation 156.7 ns/op 1 alloc 240 B ~6.4M events/sec
XML Generation 558.9 ns/op 4 allocs 360 B ~1.8M events/sec
XML Parsing 4.9 μs/op 73 allocs 3.4 KB ~200K events/sec
Type Validation
Type Pattern Speed Allocations Throughput
Simple Types (a-f-G) 22.6 ns/op 0 allocs ~44M validations/sec
Complex Types (a-f-G-E-X-N) 26.7 ns/op 0 allocs ~37M validations/sec
Wildcards (a-f-G-*) 41.4 ns/op 1 alloc ~24M validations/sec
Catalog Operations
Operation Speed Allocations Throughput
Type Lookup 17.3 ns/op 0 allocs ~57M lookups/sec
Search by Description 72.4 μs/op 4 allocs ~13K searches/sec
Search by Full Name 104.7 μs/op 5 allocs ~9K searches/sec
Key Performance Features
  • Zero-allocation lookups: Type catalog operations don't allocate memory
  • Object pooling: XML parsing reuses event objects to minimize GC pressure
  • Optimized validation: Fast-path validation for common type patterns
  • Efficient searching: Pre-computed uppercase strings for case-insensitive search
  • Minimal serialization overhead: Direct byte buffer manipulation for XML generation
Real-World Scenarios

High-frequency tracking: Process 200,000+ position updates per second Bulk operations: Validate millions of type codes with zero GC impact
Memory-constrained environments: Minimal allocation footprint Low-latency systems: Sub-microsecond event processing

Benchmarks run on Apple M4 with Go 1.21. Your mileage may vary by platform.

Documentation

For detailed documentation and examples, see:

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Project History

Originally created by @pdfinn. All core functionality and initial versions developed prior to organisational transfer.

Documentation

Overview

Package cotlib implements the Cursor on Target (CoT) protocol for Go.

The package provides data structures and utilities for parsing and generating CoT messages, as well as a comprehensive type catalog system for working with CoT type codes.

Type Catalog

The type catalog system provides a way to work with CoT type codes and their metadata. Each type code (e.g., "a-f-G-E-X-N") has associated metadata:

  • Full Name: A hierarchical name (e.g., "Gnd/Equip/Nbc Equipment")
  • Description: A human-readable description (e.g., "NBC EQUIPMENT")

The catalog supports several operations:

  • Looking up metadata for a specific type code
  • Searching for types by description or full name
  • Validating type codes
  • Registering custom type codes

Example usage:

// Look up type metadata
fullName, err := cotlib.GetTypeFullName("a-f-G-E-X-N")
if err != nil {
    log.Fatal(err)
}
fmt.Printf("Full name: %s\n", fullName)

// Search for types
types := cotlib.FindTypesByDescription("NBC")
for _, t := range types {
    fmt.Printf("Found type: %s (%s)\n", t.Name, t.Description)
}

Thread Safety

All operations on the type catalog are thread-safe. The catalog uses internal synchronization to ensure safe concurrent access.

Custom Types

Applications can register custom type codes using RegisterCoTType. These custom types must follow the standard CoT type format and will be validated before registration.

For more information about CoT types and their format, see: https://www.mitre.org/sites/default/files/pdf/09_4937.pdf

Security features include:

  • XML parsing restrictions to prevent XXE attacks
  • Input validation on all fields
  • Strict coordinate range enforcement
  • Time field validation to prevent time-based attacks
  • Secure logging practices
  • Detail extension isolation

For more information about CoT, see:

The package follows these design principles:

  • High cohesion: focused on CoT event parsing and serialization
  • Low coupling: separated concerns for expansions and transport
  • Composition over inheritance: nested sub-structures for detail fields
  • Full schema coverage: implements Event.xsd with example extensions
  • Secure by design: validates inputs and prevents common attacks
Example (RoundTripStrokeColorUsericon)
package main

import (
	"bytes"
	"fmt"

	"github.com/NERVsystems/cotlib"
)

func main() {
	evt, _ := cotlib.NewEvent("EX-UI", "a-f-G", 0, 0, 0)
	evt.StrokeColor = "ff0000ff"
	evt.UserIcon = "icon.png"

	xmlData, _ := evt.ToXML()
	cotlib.ReleaseEvent(evt)

	out, _ := cotlib.UnmarshalXMLEvent(xmlData)
	fmt.Printf("strokeColor: %s\n", out.StrokeColor)
	fmt.Printf("usericon: %s\n", out.UserIcon)
	outXML, _ := out.ToXML()
	fmt.Printf("round-trip equal: %v\n", bytes.Equal(xmlData, outXML))
	cotlib.ReleaseEvent(out)
}
Output:

strokeColor: ff0000ff
usericon: icon.png
round-trip equal: true
Example (TypePredicates)

Example_typePredicates demonstrates using type predicates

package main

import (
	"fmt"

	"github.com/NERVsystems/cotlib"
)

func main() {
	// Create some example events
	events := []*cotlib.Event{
		{Type: "a-f-G-U-C"}, // Friendly ground combat unit
		{Type: "a-h-A-M-F"}, // Hostile fixed wing aircraft
		{Type: "b-d-c-n-r"}, // NBC radiation detection
		{Type: "t-s-i-e"},   // ISR EO tasking
	}

	// Test various predicates
	predicates := []string{"atom", "friend", "hostile", "ground", "air"}

	for _, evt := range events {
		fmt.Printf("\nEvent type: %s\n", evt.Type)
		for _, pred := range predicates {
			if evt.Is(pred) {
				fmt.Printf("  Matches predicate: %s\n", pred)
			}
		}
	}

}
Output:

Event type: a-f-G-U-C
  Matches predicate: atom
  Matches predicate: friend
  Matches predicate: ground

Event type: a-h-A-M-F
  Matches predicate: atom
  Matches predicate: hostile
  Matches predicate: air

Event type: b-d-c-n-r
  Matches predicate: atom

Event type: t-s-i-e
  Matches predicate: atom

Index

Examples

Constants

View Source
const (

	// CotTimeFormat is the standard time format for CoT messages (Zulu time, no offset)
	// Format: "2006-01-02T15:04:05Z" (UTC without timezone offset)
	CotTimeFormat = "2006-01-02T15:04:05Z"
)

Security limits for XML parsing and validation

Variables

View Source
var (
	ErrInvalidInput     = fmt.Errorf("invalid input")
	ErrInvalidLatitude  = fmt.Errorf("invalid latitude")
	ErrInvalidLongitude = fmt.Errorf("invalid longitude")
	ErrInvalidUID       = fmt.Errorf("invalid UID")
)

Error sentinels for validation

Functions

func FindTypes

func FindTypes(query string) []cottypes.Type

FindTypes returns all types matching the given query

func FindTypesByDescription

func FindTypesByDescription(desc string) []cottypes.Type

FindTypesByDescription searches for types matching the given description. The search is case-insensitive and matches partial descriptions.

For example:

  • "NBC" finds all types containing "NBC" in their description
  • "EQUIPMENT" finds all equipment-related types
  • "COMBAT" finds all combat-related types

This is useful for building search interfaces and type discovery tools. Returns an empty slice if no matches are found.

Example
package main

import (
	"fmt"
	"sort"

	"github.com/NERVsystems/cotlib"
)

func main() {
	types := cotlib.FindTypesByDescription("NBC EQUIPMENT")
	// Sort by name for consistent output
	sort.Slice(types, func(i, j int) bool {
		return types[i].Name < types[j].Name
	})
	for _, t := range types {
		fmt.Printf("Found type: %s (%s)\n", t.Name, t.Description)
	}
}
Output:

Found type: a-f-G-E-X-N (NBC EQUIPMENT)
Found type: a-h-G-E-X-N (NBC EQUIPMENT)
Found type: a-n-G-E-X-N (NBC EQUIPMENT)
Found type: a-u-G-E-X-N (NBC EQUIPMENT)

func FindTypesByFullName

func FindTypesByFullName(name string) []cottypes.Type

FindTypesByFullName searches for types matching the given full name. The search is case-insensitive and matches partial names.

For example:

  • "Nbc Equipment" finds all NBC equipment types
  • "Ground" finds all ground-based types
  • "Vehicle" finds all vehicle types

This is useful for finding types based on their hierarchical classification. Returns an empty slice if no matches are found.

Example
package main

import (
	"fmt"
	"sort"

	"github.com/NERVsystems/cotlib"
)

func main() {
	types := cotlib.FindTypesByFullName("Gnd/Equip/Nbc Equipment")
	// Sort by name for consistent output
	sort.Slice(types, func(i, j int) bool {
		return types[i].Name < types[j].Name
	})
	for _, t := range types {
		fmt.Printf("Found type: %s (%s)\n", t.Name, t.FullName)
	}
}
Output:

Found type: a-f-G-E-X-N (Gnd/Equip/Nbc Equipment)
Found type: a-h-G-E-X-N (Gnd/Equip/Nbc Equipment)
Found type: a-n-G-E-X-N (Gnd/Equip/Nbc Equipment)
Found type: a-u-G-E-X-N (Gnd/Equip/Nbc Equipment)

func GetHowDescriptor added in v0.2.7

func GetHowDescriptor(how string) (string, error)

GetHowDescriptor returns a human-readable description of the how value. For example: "h-g-i-g-o" returns "gps".

func GetRelationDescription added in v0.2.7

func GetRelationDescription(relation string) (string, error)

GetRelationDescription returns a human-readable description of the relation value. For example: "p-p" returns "parent-point".

func GetTypeDescription

func GetTypeDescription(name string) (string, error)

GetTypeDescription returns the human-readable description for a CoT type. For example, "a-f-G-E-X-N" returns "NBC EQUIPMENT".

The description is a concise explanation of what the type represents, suitable for display in user interfaces and logs.

Returns an error if the type is not registered in the catalog.

Example
package main

import (
	"fmt"

	"github.com/NERVsystems/cotlib"
)

func main() {
	desc, err := cotlib.GetTypeDescription("a-f-G-E-X-N")
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}
	fmt.Printf("Description: %s\n", desc)
}
Output:

Description: NBC EQUIPMENT

func GetTypeFullName

func GetTypeFullName(name string) (string, error)

GetTypeFullName returns the full hierarchical name for a CoT type. For example, "a-f-G-E-X-N" returns "Gnd/Equip/Nbc Equipment".

The full name represents the type's position in the CoT type hierarchy, making it useful for building user interfaces and documentation.

Returns an error if the type is not registered in the catalog.

Example
package main

import (
	"fmt"

	"github.com/NERVsystems/cotlib"
)

func main() {
	fullName, err := cotlib.GetTypeFullName("a-f-G-E-X-N")
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}
	fmt.Printf("Full name: %s\n", fullName)
}
Output:

Full name: Gnd/Equip/Nbc Equipment

func LoadCoTTypesFromFile

func LoadCoTTypesFromFile(ctx context.Context, path string) error

LoadCoTTypesFromFile loads CoT types from a file

func LoggerFromContext added in v0.2.7

func LoggerFromContext(ctx context.Context) *slog.Logger

LoggerFromContext retrieves the logger from context or returns slog.Default.

func LookupType

func LookupType(name string) (cottypes.Type, bool)

LookupType returns the Type for the given name if it exists

func RegisterAllCoTTypes

func RegisterAllCoTTypes() error

RegisterAllCoTTypes is a no-op since XML is already embedded

func RegisterCoTType

func RegisterCoTType(name string)

RegisterCoTType adds a specific CoT type to the valid types registry It does not log individual type registrations to avoid log spam

func RegisterCoTTypesFromFile

func RegisterCoTTypesFromFile(ctx context.Context, filename string) error

RegisterCoTTypesFromFile loads and registers CoT types from an XML file

func RegisterCoTTypesFromReader

func RegisterCoTTypesFromReader(ctx context.Context, r io.Reader) error

RegisterCoTTypesFromReader loads and registers CoT types from an XML reader

func RegisterCoTTypesFromXMLContent

func RegisterCoTTypesFromXMLContent(ctx context.Context, xmlContent string) error

RegisterCoTTypesFromXMLContent registers CoT types from the given XML content string This is particularly useful for embedding the CoTtypes.xml content directly in code

func ReleaseEvent added in v0.2.6

func ReleaseEvent(e *Event)

ReleaseEvent returns an Event to the internal pool after resetting all fields.

The provided pointer should no longer be used after calling this function.

func SetEventHowFromDescriptor added in v0.2.7

func SetEventHowFromDescriptor(event *Event, descriptor string) error

SetEventHowFromDescriptor sets the how field on an event using a descriptor. For example: SetEventHowFromDescriptor(event, "gps") sets how to "h-g-i-g-o".

func SetLogger

func SetLogger(l *slog.Logger)

SetLogger sets the package-level logger

func SetMaxElementCount added in v0.2.7

func SetMaxElementCount(max int64)

SetMaxElementCount sets the maximum allowed number of XML elements

func SetMaxElementDepth added in v0.2.7

func SetMaxElementDepth(max int64)

SetMaxElementDepth sets the maximum depth of XML elements

func SetMaxTokenLen added in v0.2.7

func SetMaxTokenLen(max int64)

SetMaxTokenLen sets the maximum length for any single XML token

func SetMaxValueLen

func SetMaxValueLen(max int64)

SetMaxValueLen sets the maximum allowed length for XML attribute values and character data This is used to prevent memory exhaustion attacks via large XML payloads

func SetMaxXMLSize added in v0.2.7

func SetMaxXMLSize(max int64)

SetMaxXMLSize sets the maximum allowed size for XML input

func ValidateHow added in v0.2.7

func ValidateHow(how string) error

ValidateHow checks if a how value is valid according to the CoT catalog. How values indicate the source or method of position determination.

func ValidateLatLon

func ValidateLatLon(lat, lon float64) error

ValidateLatLon checks if latitude and longitude are within valid ranges

func ValidateRelation added in v0.2.7

func ValidateRelation(relation string) error

ValidateRelation checks if a relation value is valid according to the CoT catalog. Relation values indicate the relationship type in link elements.

func ValidateType

func ValidateType(typ string) error

ValidateType checks if a CoT type is valid

Example
package main

import (
	"fmt"

	"github.com/NERVsystems/cotlib"
)

func main() {
	// Test various CoT types
	types := []string{
		"a-f-G",      // Friendly ground
		"a-h-A",      // Hostile air
		"b-d",        // Detection
		"t-x-takp-v", // TAK presence
		"invalid",    // Invalid type
	}

	for _, typ := range types {
		err := cotlib.ValidateType(typ)
		fmt.Printf("Type %s: %v\n", typ, err == nil)
	}

}
Output:

Type a-f-G: true
Type a-h-A: true
Type b-d: true
Type t-x-takp-v: true
Type invalid: false

func ValidateUID

func ValidateUID(uid string) error

ValidateUID checks if a UID is valid. It rejects empty values, leading hyphens, double dots, whitespace, and UIDs longer than 64 characters.

func WithLogger

func WithLogger(ctx context.Context, l *slog.Logger) context.Context

WithLogger adds a logger to the context

Types

type Archive added in v0.2.8

type Archive struct {
	Raw RawMessage
}

Archive represents the TAK archive extension.

func (Archive) MarshalXML added in v0.2.8

func (a Archive) MarshalXML(enc *xml.Encoder, start xml.StartElement) error

func (*Archive) UnmarshalXML added in v0.2.8

func (a *Archive) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error

type AttachmentList added in v0.2.8

type AttachmentList struct {
	Raw RawMessage
}

AttachmentList represents the TAK attachmentList extension.

func (AttachmentList) MarshalXML added in v0.2.8

func (a AttachmentList) MarshalXML(enc *xml.Encoder, start xml.StartElement) error

func (*AttachmentList) UnmarshalXML added in v0.2.8

func (a *AttachmentList) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error

type Bullseye added in v0.2.8

type Bullseye struct {
	Raw RawMessage
}

Bullseye represents the TAK bullseye extension.

func (Bullseye) MarshalXML added in v0.2.8

func (b Bullseye) MarshalXML(enc *xml.Encoder, start xml.StartElement) error

func (*Bullseye) UnmarshalXML added in v0.2.8

func (b *Bullseye) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error

type Chat added in v0.2.8

type Chat struct {
	Raw RawMessage
}

Chat represents the TAK __chat extension.

func (Chat) MarshalXML added in v0.2.8

func (c Chat) MarshalXML(enc *xml.Encoder, start xml.StartElement) error

func (*Chat) UnmarshalXML added in v0.2.8

func (c *Chat) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error

type ChatReceipt added in v0.2.8

type ChatReceipt struct {
	Raw RawMessage
}

ChatReceipt represents the TAK __chatReceipt extension.

func (ChatReceipt) MarshalXML added in v0.2.8

func (c ChatReceipt) MarshalXML(enc *xml.Encoder, start xml.StartElement) error

func (*ChatReceipt) UnmarshalXML added in v0.2.8

func (c *ChatReceipt) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error

type CoTTime

type CoTTime time.Time

CoTTime represents a time in CoT format (UTC without timezone offset)

func (CoTTime) MarshalXML

func (t CoTTime) MarshalXML(e *xml.Encoder, start xml.StartElement) error

MarshalXML implements xml.Marshaler

func (CoTTime) MarshalXMLAttr

func (t CoTTime) MarshalXMLAttr(name xml.Name) (xml.Attr, error)

MarshalXMLAttr implements xml.MarshalerAttr

func (CoTTime) Time

func (t CoTTime) Time() time.Time

Time returns the underlying time.Time value

func (*CoTTime) UnmarshalXML

func (t *CoTTime) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

UnmarshalXML implements xml.Unmarshaler

func (*CoTTime) UnmarshalXMLAttr

func (t *CoTTime) UnmarshalXMLAttr(attr xml.Attr) error

UnmarshalXMLAttr implements xml.UnmarshalerAttr

type ColorExtension added in v0.2.8

type ColorExtension struct {
	Raw RawMessage
}

ColorExtension represents the TAK color extension.

func (ColorExtension) MarshalXML added in v0.2.8

func (c ColorExtension) MarshalXML(enc *xml.Encoder, start xml.StartElement) error

func (*ColorExtension) UnmarshalXML added in v0.2.8

func (c *ColorExtension) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error

type Contact

type Contact struct {
	Callsign string `xml:"callsign,attr,omitempty"`
}

Contact represents contact information

type Detail

type Detail struct {
	Group             *Group             `xml:"group,omitempty"`
	Contact           *Contact           `xml:"contact,omitempty"`
	Chat              *Chat              `xml:"__chat,omitempty"`
	ChatReceipt       *ChatReceipt       `xml:"__chatReceipt,omitempty"`
	Geofence          *Geofence          `xml:"__geofence,omitempty"`
	ServerDestination *ServerDestination `xml:"__serverdestination,omitempty"`
	Video             *Video             `xml:"__video,omitempty"`
	GroupExtension    *GroupExtension    `xml:"__group,omitempty"`
	Archive           *Archive           `xml:"archive,omitempty"`
	AttachmentList    *AttachmentList    `xml:"attachmentList,omitempty"`
	Environment       *Environment       `xml:"environment,omitempty"`
	FileShare         *FileShare         `xml:"fileshare,omitempty"`
	PrecisionLocation *PrecisionLocation `xml:"precisionlocation,omitempty"`
	Takv              *Takv              `xml:"takv,omitempty"`
	Track             *Track             `xml:"track,omitempty"`
	Mission           *Mission           `xml:"mission,omitempty"`
	Status            *Status            `xml:"status,omitempty"`
	Shape             *Shape             `xml:"shape,omitempty"`
	StrokeColor       *StrokeColor       `xml:"strokecolor,omitempty"`
	StrokeWeight      *StrokeWeight      `xml:"strokeweight,omitempty"`
	FillColor         *FillColor         `xml:"fillcolor,omitempty"`
	LabelsOn          *LabelsOn          `xml:"labelson,omitempty"`
	ColorExtension    *ColorExtension    `xml:"color,omitempty"`
	UserIcon          *UserIcon          `xml:"usericon,omitempty"`
	Bullseye          *Bullseye          `xml:"bullseye,omitempty"`
	RouteInfo         *RouteInfo         `xml:"routeInfo,omitempty"`
	Remarks           *Remarks           `xml:"remarks,omitempty"`
	Unknown           []RawMessage       `xml:"-"`
}

Detail contains additional information about an event

func (*Detail) MarshalXML added in v0.2.8

func (d *Detail) MarshalXML(enc *xml.Encoder, start xml.StartElement) error

MarshalXML implements xml.Marshaler for Detail.

func (*Detail) UnmarshalXML added in v0.2.8

func (d *Detail) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error

UnmarshalXML implements xml.Unmarshaler for Detail.

type Environment added in v0.2.8

type Environment struct {
	Raw RawMessage
}

Environment represents the TAK environment extension.

func (Environment) MarshalXML added in v0.2.8

func (e Environment) MarshalXML(enc *xml.Encoder, start xml.StartElement) error

func (*Environment) UnmarshalXML added in v0.2.8

func (e *Environment) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error

type Event

type Event struct {
	XMLName xml.Name `xml:"event"`
	Version string   `xml:"version,attr"`
	Uid     string   `xml:"uid,attr"`
	Type    string   `xml:"type,attr"`
	How     string   `xml:"how,attr,omitempty"`
	Time    CoTTime  `xml:"time,attr"`
	Start   CoTTime  `xml:"start,attr"`
	Stale   CoTTime  `xml:"stale,attr"`
	Point   Point    `xml:"point"`
	Detail  *Detail  `xml:"detail,omitempty"`
	Links   []Link   `xml:"link,omitempty"`
	// StrokeColor is an ARGB hex color used for drawing events.
	StrokeColor string `xml:"strokeColor,attr,omitempty"`
	// UserIcon specifies a custom icon URL or resource for the event.
	UserIcon string `xml:"usericon,attr,omitempty"`
}

Event represents a CoT event message

func NewEvent

func NewEvent(uid, typ string, lat, lon, hae float64) (*Event, error)

NewEvent creates a new CoT event with the given parameters

Example
package main

import (
	"fmt"

	"github.com/NERVsystems/cotlib"
)

func main() {
	// Create a new event with a friendly ground unit
	event, err := cotlib.NewEvent("test123", "a-f-G", 30.0, -85.0, 0.0)
	if err != nil {
		fmt.Printf("Error creating event: %v\n", err)
		return
	}

	// Add some details
	event.Detail = &cotlib.Detail{
		Contact: &cotlib.Contact{
			Callsign: "TEST-1",
		},
	}

	// Print event details
	fmt.Printf("Event Type: %s\n", event.Type)
	fmt.Printf("Location: %.2f, %.2f\n", event.Point.Lat, event.Point.Lon)
	fmt.Printf("Callsign: %s\n", event.Detail.Contact.Callsign)

}
Output:

Event Type: a-f-G
Location: 30.00, -85.00
Callsign: TEST-1

func NewPresenceEvent

func NewPresenceEvent(uid string, lat, lon, hae float64) (*Event, error)

NewPresenceEvent creates a new presence event (t-x-takp-v)

func UnmarshalXMLEvent

func UnmarshalXMLEvent(data []byte) (*Event, error)

UnmarshalXMLEvent parses an XML byte slice into an Event. The returned Event is obtained from an internal pool; callers should release it with ReleaseEvent when finished. The function uses the standard library's encoding/xml Decoder under the hood.

func UnmarshalXMLEventCtx added in v0.2.8

func UnmarshalXMLEventCtx(ctx context.Context, data []byte) (*Event, error)

UnmarshalXMLEventCtx parses an XML byte slice into an Event using the provided context for logging. The returned Event is obtained from an internal pool and must be released with ReleaseEvent when finished.

func (e *Event) AddLink(link *Link)

AddLink adds a link to the event

func (e *Event) AddValidatedLink(uid, linkType, relation string) error

AddValidatedLink adds a link to the event after validating the relation and type.

func (*Event) InjectIdentity

func (e *Event) InjectIdentity(selfUid, groupName, groupRole string)

InjectIdentity adds identity information to the event

Example
package main

import (
	"fmt"

	"github.com/NERVsystems/cotlib"
)

func main() {
	// Create a new event
	event, err := cotlib.NewEvent("test123", "a-f-G", 30.0, -85.0, 0.0)
	if err != nil {
		fmt.Printf("Error creating event: %v\n", err)
		return
	}

	// Inject identity information
	event.InjectIdentity("self123", "Blue", "HQ")

	// Print identity details
	if event.Detail != nil && event.Detail.Group != nil {
		fmt.Printf("Group: %s\n", event.Detail.Group.Name)
		fmt.Printf("Role: %s\n", event.Detail.Group.Role)
	}

}
Output:

Group: Blue
Role: HQ

func (*Event) Is

func (e *Event) Is(pred string) bool

Is checks if the event matches a predicate

Example
package main

import (
	"fmt"

	"github.com/NERVsystems/cotlib"
)

func main() {
	// Create a friendly ground unit event
	event, err := cotlib.NewEvent("test123", "a-f-G", 30.0, -85.0, 0.0)
	if err != nil {
		fmt.Printf("Error creating event: %v\n", err)
		return
	}

	// Check various predicates
	fmt.Printf("Is friendly: %v\n", event.Is("friend"))
	fmt.Printf("Is hostile: %v\n", event.Is("hostile"))
	fmt.Printf("Is ground: %v\n", event.Is("ground"))
	fmt.Printf("Is air: %v\n", event.Is("air"))

}
Output:

Is friendly: true
Is hostile: false
Is ground: true
Is air: false

func (*Event) ToXML

func (e *Event) ToXML() ([]byte, error)

ToXML serialises an Event to CoT-compliant XML. Attribute values are escaped to prevent XML-injection. The <point> element is always emitted so that the zero coordinate (0° N 0° E) is representable.

func (*Event) Validate

func (e *Event) Validate() error

Validate checks if the event is valid

func (*Event) ValidateAt added in v0.2.6

func (e *Event) ValidateAt(now time.Time) error

ValidateAt checks if the event is valid using the provided reference time

type FileShare added in v0.2.8

type FileShare struct {
	Raw RawMessage
}

FileShare represents the TAK fileshare extension.

func (FileShare) MarshalXML added in v0.2.8

func (f FileShare) MarshalXML(enc *xml.Encoder, start xml.StartElement) error

func (*FileShare) UnmarshalXML added in v0.2.8

func (f *FileShare) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error

type FillColor added in v0.2.8

type FillColor struct {
	Raw RawMessage
}

FillColor represents the TAK fillcolor extension.

func (FillColor) MarshalXML added in v0.2.8

func (fc FillColor) MarshalXML(enc *xml.Encoder, start xml.StartElement) error

func (*FillColor) UnmarshalXML added in v0.2.8

func (fc *FillColor) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error

type Geofence added in v0.2.8

type Geofence struct {
	Raw RawMessage
}

Geofence represents the TAK __geofence extension.

func (Geofence) MarshalXML added in v0.2.8

func (g Geofence) MarshalXML(enc *xml.Encoder, start xml.StartElement) error

func (*Geofence) UnmarshalXML added in v0.2.8

func (g *Geofence) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error

type Group

type Group struct {
	Name string `xml:"name,attr"`
	Role string `xml:"role,attr"`
}

Group represents a group affiliation

type GroupExtension added in v0.2.8

type GroupExtension struct {
	Raw RawMessage
}

GroupExtension represents the TAK __group extension.

func (GroupExtension) MarshalXML added in v0.2.8

func (g GroupExtension) MarshalXML(enc *xml.Encoder, start xml.StartElement) error

func (*GroupExtension) UnmarshalXML added in v0.2.8

func (g *GroupExtension) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error

type LabelsOn added in v0.2.8

type LabelsOn struct {
	Raw RawMessage
}

LabelsOn represents the TAK labelson extension.

func (LabelsOn) MarshalXML added in v0.2.8

func (lo LabelsOn) MarshalXML(enc *xml.Encoder, start xml.StartElement) error

func (*LabelsOn) UnmarshalXML added in v0.2.8

func (lo *LabelsOn) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error
type Link struct {
	Uid      string `xml:"uid,attr"`
	Type     string `xml:"type,attr"`
	Relation string `xml:"relation,attr"`
}

Link represents a relationship to another event

type Mission added in v0.2.8

type Mission struct {
	Raw RawMessage
}

Mission represents the TAK mission extension.

func (Mission) MarshalXML added in v0.2.8

func (m Mission) MarshalXML(enc *xml.Encoder, start xml.StartElement) error

func (*Mission) UnmarshalXML added in v0.2.8

func (m *Mission) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error

type Point

type Point struct {
	Lat float64 `xml:"lat,attr"` // Latitude in degrees
	Lon float64 `xml:"lon,attr"` // Longitude in degrees
	Hae float64 `xml:"hae,attr"` // Height above ellipsoid in meters
	Ce  float64 `xml:"ce,attr"`  // Circular error in meters
	Le  float64 `xml:"le,attr"`  // Linear error in meters
}

Point represents a location in 3D space with error estimates

func (*Point) Validate

func (p *Point) Validate() error

Validate checks if the point coordinates and errors are valid

type PrecisionLocation added in v0.2.8

type PrecisionLocation struct {
	Raw RawMessage
}

PrecisionLocation represents the TAK precisionlocation extension.

func (PrecisionLocation) MarshalXML added in v0.2.8

func (p PrecisionLocation) MarshalXML(enc *xml.Encoder, start xml.StartElement) error

func (*PrecisionLocation) UnmarshalXML added in v0.2.8

func (p *PrecisionLocation) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error

type RawMessage added in v0.2.8

type RawMessage []byte

RawMessage represents raw XML data preserved during decoding.

type Remarks added in v0.2.8

type Remarks struct {
	Raw RawMessage
}

Remarks represents the TAK remarks extension.

func (Remarks) MarshalXML added in v0.2.8

func (r Remarks) MarshalXML(enc *xml.Encoder, start xml.StartElement) error

func (*Remarks) UnmarshalXML added in v0.2.8

func (r *Remarks) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error

type RouteInfo added in v0.2.8

type RouteInfo struct {
	Raw RawMessage
}

RouteInfo represents the TAK routeInfo extension.

func (RouteInfo) MarshalXML added in v0.2.8

func (ri RouteInfo) MarshalXML(enc *xml.Encoder, start xml.StartElement) error

func (*RouteInfo) UnmarshalXML added in v0.2.8

func (ri *RouteInfo) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error

type ServerDestination added in v0.2.8

type ServerDestination struct {
	Raw RawMessage
}

ServerDestination represents the TAK __serverdestination extension.

func (ServerDestination) MarshalXML added in v0.2.8

func (sd ServerDestination) MarshalXML(enc *xml.Encoder, start xml.StartElement) error

func (*ServerDestination) UnmarshalXML added in v0.2.8

func (sd *ServerDestination) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error

type Shape added in v0.2.8

type Shape struct {
	Raw RawMessage
}

Shape represents the TAK shape extension.

func (Shape) MarshalXML added in v0.2.8

func (s Shape) MarshalXML(enc *xml.Encoder, start xml.StartElement) error

func (*Shape) UnmarshalXML added in v0.2.8

func (s *Shape) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error

type Status added in v0.2.8

type Status struct {
	Raw RawMessage
}

Status represents the TAK status extension.

func (Status) MarshalXML added in v0.2.8

func (s Status) MarshalXML(enc *xml.Encoder, start xml.StartElement) error

func (*Status) UnmarshalXML added in v0.2.8

func (s *Status) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error

type StrokeColor added in v0.2.8

type StrokeColor struct {
	Raw RawMessage
}

StrokeColor represents the TAK strokecolor extension.

func (StrokeColor) MarshalXML added in v0.2.8

func (sc StrokeColor) MarshalXML(enc *xml.Encoder, start xml.StartElement) error

func (*StrokeColor) UnmarshalXML added in v0.2.8

func (sc *StrokeColor) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error

type StrokeWeight added in v0.2.8

type StrokeWeight struct {
	Raw RawMessage
}

StrokeWeight represents the TAK strokeweight extension.

func (StrokeWeight) MarshalXML added in v0.2.8

func (sw StrokeWeight) MarshalXML(enc *xml.Encoder, start xml.StartElement) error

func (*StrokeWeight) UnmarshalXML added in v0.2.8

func (sw *StrokeWeight) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error

type Takv added in v0.2.8

type Takv struct {
	Raw RawMessage
}

Takv represents the TAK takv extension.

func (Takv) MarshalXML added in v0.2.8

func (t Takv) MarshalXML(enc *xml.Encoder, start xml.StartElement) error

func (*Takv) UnmarshalXML added in v0.2.8

func (t *Takv) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error

type Track added in v0.2.8

type Track struct {
	Raw RawMessage
}

Track represents the TAK track extension.

func (Track) MarshalXML added in v0.2.8

func (t Track) MarshalXML(enc *xml.Encoder, start xml.StartElement) error

func (*Track) UnmarshalXML added in v0.2.8

func (t *Track) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error

type UserIcon added in v0.2.8

type UserIcon struct {
	Raw RawMessage
}

UserIcon represents the TAK usericon extension.

func (UserIcon) MarshalXML added in v0.2.8

func (ui UserIcon) MarshalXML(enc *xml.Encoder, start xml.StartElement) error

func (*UserIcon) UnmarshalXML added in v0.2.8

func (ui *UserIcon) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error

type Video added in v0.2.8

type Video struct {
	Raw RawMessage
}

Video represents the TAK __video extension.

func (Video) MarshalXML added in v0.2.8

func (v Video) MarshalXML(enc *xml.Encoder, start xml.StartElement) error

func (*Video) UnmarshalXML added in v0.2.8

func (v *Video) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error

Directories

Path Synopsis
cmd
cotgen command
logcheck command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL