ronantakizawa/codereview-bench huggingface dataset:
Repository: istio/istio
File: pilot/pkg/networking/core/tracing.go (Go)

Code before:
					Value: clusterID,
				},
			},
		},
		{
			Tag: "istio.downstream.workload",
			Type: &tracing.CustomTag_Value{
				Value: "%CEL(filter_state.downstream_peer.workload)%",
			},
		},
		{
			Tag: "istio.downstream.workload",
			Type: &tracing.CustomTag_Value{
				Value: "%CEL(filter_state.downstream_peer.workload)%",
			},
		},
		{
			Tag: "istio.downstream",
			Type: &tracing.CustomTag_Value{
				Value: "%FILTER_STATE(downstream_peer:TYPED)%",
			},
		},
		{
			Tag: "istio.upstream.workload",
			Type: &tracing.CustomTag_Value{
				Value: "%CEL(filter_state.upstream_peer.workload)%",
			},
		},
		{
			Tag: "istio.upstream",
			Type: &tracing.CustomTag_Value{
				Value: "%FILTER_STATE(upstream_peer:TYPED)%",
			},
		},
	}
}

func configureSampling(hcmTracing *hcm.HttpConnectionManager_Tracing, providerPercentage float64) {
	hcmTracing.ClientSampling = &xdstype.Percent{
		Value: 100.0,
	}
	hcmTracing.OverallSampling = &xdstype.Percent{
		Value: 100.0,
	}
	hcmTracing.RandomSampling = &xdstype.Percent{
		Value: providerPercentage,
	}
}

func proxyConfigSamplingValue(config *meshconfig.ProxyConfig) float64 {
	// PILOT_TRACE_SAMPLING

Review comment (suggestion):
I really trie dto use `%FILTER_STATE` here, but I think we might need some changes in proxy for this to happen.

Code after:
					Value: clusterID,
				},
			},
		},
	}
	// Waypoints use filter state to expose upstream/downstream workloads.
	if node.IsWaypointProxy() {
		waypointTags := []*tracing.CustomTag{
			{
				Tag: "istio.downstream.workload",
				Type: &tracing.CustomTag_Value{
					Value: "%CEL(filter_state.downstream_peer.workload)%",
				},
			},
			{
				Tag: "istio.downstream.namespace",
				Type: &tracing.CustomTag_Value{
					Value: "%CEL(filter_state.downstream_peer.namespace)%",
				},
			},
			{
				Tag: "istio.upstream.workload",
				Type: &tracing.CustomTag_Value{
					Value: "%CEL(filter_state.upstream_peer.workload)%",
				},
			},
			{
				Tag: "istio.upstream.namespace",
				Type: &tracing.CustomTag_Value{
					Value: "%CEL(filter_state.upstream_peer.namespace)%",
				},
			},
		}
		tags = append(tags, waypointTags...)
	}

	return tags
}

func configureSampling(hcmTracing *hcm.HttpConnectionManager_Tracing, providerPercentage float64) {
	hcmTracing.ClientSampling = &xdstype.Percent{
		Value: 100.0,
	}
	hcmTracing.OverallSampling = &xdstype.Percent{
		Value: 100.0,
	}
	hcmTracing.RandomSampling = &xdstype.Percent{
		Value: providerPercentage,
	}
}
Repository: istio/istio
File: pilot/pkg/serviceregistry/kube/controller/ambient/authorization.go (Go)

Code before:
		groups = append(groups, &security.Group{
			Rules: rules,
		})
	}

	opol := &security.Authorization{
		Name: model.GetAmbientPolicyConfigName(model.ConfigKey{
			Name:      cfg.Name,
			Kind:      kind.PeerAuthentication,
			Namespace: cfg.Namespace,
		}),
		Namespace: cfg.Namespace,
		Scope:     scope,
		Action:    action,
		Groups:    groups,
	}

	return opol
}

func convertAuthorizationPolicy(rootns string, obj *securityclient.AuthorizationPolicy) (*security.Authorization, *model.StatusMessage) {
	pol := &obj.Spec

	dryRun, convErr := strconv.ParseBool(obj.Annotations[annotation.IoIstioDryRun.Name])
	if convErr != nil {
		// proceed anyway?
		log.Errorf("Unable to parse dry run annotation, encountered error %v", convErr)
	}
	polTargetRef := model.GetTargetRefs(pol)
	if len(polTargetRef) > 0 {
		// TargetRef is not intended for ztunnel
		return nil, nil
	}

	scope := security.Scope_WORKLOAD_SELECTOR
	if pol.GetSelector() == nil {
		scope = security.Scope_NAMESPACE
		// TODO: TDA
		if rootns == obj.Namespace {
			scope = security.Scope_GLOBAL // TODO: global workload?
		}
	}
	action := security.Action_ALLOW
	boilerplate := httpAllowRuleBoilerplate
	switch pol.Action {
	case v1beta1.AuthorizationPolicy_ALLOW:
	case v1beta1.AuthorizationPolicy_DENY:
		action = security.Action_DENY
		boilerplate = httpDenyRuleBoilerplate
	default:
		return nil, &model.StatusMessage{

Review comment (refactor):
```suggestion
	if convErr != nil {
		dryRun = false
```
I don't think Go defines the value of the first return value if there is an error (though in practice, it is `false`).

Code after:
	if len(rules) > 0 {
		groups = append(groups, &security.Group{
			Rules: rules,
		})
	}

	opol := &security.Authorization{
		Name: model.GetAmbientPolicyConfigName(model.ConfigKey{
			Name:      cfg.Name,
			Kind:      kind.PeerAuthentication,
			Namespace: cfg.Namespace,
		}),
		Namespace: cfg.Namespace,
		Scope:     scope,
		Action:    action,
		Groups:    groups,
	}

	return opol
}

func convertAuthorizationPolicy(rootns string, obj *securityclient.AuthorizationPolicy) (*security.Authorization, *model.StatusMessage) {
	pol := &obj.Spec

	dryRun, convErr := strconv.ParseBool(obj.Annotations[annotation.IoIstioDryRun.Name])
	if convErr != nil {
		// proceed anyway?
		log.Errorf("Unable to parse dry run annotation, encountered error %v", convErr)
	}

	if dryRun && !features.EnableWdsDryRunAuthzPol {
		msg := fmt.Sprintf("found policy \"%s/%s\" using dry-run annotation, but support for ambient dry-run authorizationPolicies isn't enabled",
			obj.Namespace, obj.Name)
		log.Debug(msg)
		return nil, &model.StatusMessage{
			Reason:  "UnsupportedValue",
			Message: msg,
		}
	}

	polTargetRef := model.GetTargetRefs(pol)
	if len(polTargetRef) > 0 {
		// TargetRef is not intended for ztunnel
		return nil, nil
	}

	scope := security.Scope_WORKLOAD_SELECTOR
	if pol.GetSelector() == nil {
		scope = security.Scope_NAMESPACE
		// TODO: TDA
		if rootns == obj.Namespace {
Repository: istio/istio
File: pilot/pkg/bootstrap/server_test.go (Go)

Code before:

			httpsReadyClient := &http.Client{
				Timeout: time.Second,
				Transport: &http.Transport{
					TLSClientConfig: &tls.Config{
						InsecureSkipVerify: true,
						CipherSuites:       c.clientCipherSuites,
						MinVersion:         tls.VersionTLS12,
						MaxVersion:         tls.VersionTLS12,
					},
				},
			}

			retry.UntilSuccessOrFail(t, func() error {
				response, err := httpsReadyClient.Get("https://" + s.httpsAddr + "/ready")
				if response != nil {
					defer response.Body.Close()
				}
				if c.expectSuccess && err != nil {
					return fmt.Errorf("expect success but got err %v", err)
				}
				if !c.expectSuccess && err == nil {
					return fmt.Errorf("expect failure but succeeded")
				}
				return nil
			})
		})
	}
}

func TestIstiodMinTLSVersion(t *testing.T) {
	cases := []struct {
		name                string
		serverMinTLSVersion uint16
		clientMinTLSVersion uint16
		clientMaxTLSVersion uint16
		expectSuccess       bool
	}{
		{
			name:          "default TLS version",
			expectSuccess: true,
		},
		{
			name:                "client and server TLS versions compatible",
			serverMinTLSVersion: tls.VersionTLS12,
			clientMinTLSVersion: tls.VersionTLS12,
			clientMaxTLSVersion: tls.VersionTLS13,
			expectSuccess:       true,
		},
		{
			name:                "server requires TLS 1.3, client supports it",

Review comment (suggestion):
This was previously removed but the test appears non-functional without it and I needed something similar for the `TestIstiodMinTLSVersion` so I added it back in here.

Code after:

			httpsReadyClient := &http.Client{
				Timeout: time.Second,
				Transport: &http.Transport{
					TLSClientConfig: &tls.Config{
						InsecureSkipVerify: true, //nolint:gosec
						CipherSuites:       c.clientCipherSuites,
						MinVersion:         tls.VersionTLS12,
						MaxVersion:         tls.VersionTLS12,
					},
				},
			}

			retry.UntilSuccessOrFail(t, func() error {
				response, err := httpsReadyClient.Get("https://" + s.httpsAddr + "/ready")
				if response != nil {
					defer response.Body.Close()
				}
				if c.expectSuccess && err != nil {
					return fmt.Errorf("expect success but got err %v", err)
				}
				if !c.expectSuccess && err == nil {
					return fmt.Errorf("expect failure but succeeded")
				}
				return nil
			})
		})
	}
}

func TestIstiodMinTLSVersion(t *testing.T) {
	cases := []struct {
		name                string
		serverMinTLSVersion uint16
		clientMinTLSVersion uint16
		clientMaxTLSVersion uint16
		expectSuccess       bool
	}{
		{
			name:          "default TLS version",
			expectSuccess: true,
		},
		{
			name:                "client and server TLS versions compatible",
			serverMinTLSVersion: tls.VersionTLS12,
			clientMinTLSVersion: tls.VersionTLS12,
			clientMaxTLSVersion: tls.VersionTLS13,
			expectSuccess:       true,
		},
		{
			name:                "server requires TLS 1.3, client supports it",
Repository: istio/istio
File: pilot/pkg/xds/debug_test.go (Go)

Code before:
	s := xdsfake.NewFakeDiscoveryServer(t, xdsfake.FakeOptions{})

	// Create a proxy in production namespace
	ads := s.ConnectADS().WithID("sidecar~10.0.0.1~test.production~production.svc.cluster.local")
	ads.RequestResponseAck(t, &discovery.DiscoveryRequest{TypeUrl: v3.ClusterType})

	tests := []struct {
		name       string
		callerNS   string
		proxyID    string
		wantStatus int
	}{
		{
			name:       "system namespace accesses any proxy",
			callerNS:   "istio-system",
			proxyID:    "test.production",
			wantStatus: 200,
		},
		{
			name:       "same namespace allowed",
			callerNS:   "production",
			proxyID:    "test.production",
			wantStatus: 200,
		},
		{
			name:       "cross-namespace denied - this would FAIL before fix",
			callerNS:   "staging",
			proxyID:    "test.production",
			wantStatus: 404, // Returns 404 when proxy not accessible
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			req, _ := http.NewRequest(http.MethodGet, "/debug/config_dump?proxyID="+tt.proxyID, nil)

			// Inject caller namespace into context (simulating auth middleware)
			ctx := context.WithValue(req.Context(), xds.CallerNamespaceKey{}, tt.callerNS)
			req = req.WithContext(ctx)

			rr := httptest.NewRecorder()
			handler := http.HandlerFunc(s.Discovery.ConfigDump)
			handler.ServeHTTP(rr, req)

			assert.Equal(t, rr.Code, tt.wantStatus,
				"namespace=%s accessing proxyID=%s", tt.callerNS, tt.proxyID)
		})
	}
}


Review comment (suggestion):
```suggestion
			name:       "cross-namespace denied",
```

Code after:
	s := xdsfake.NewFakeDiscoveryServer(t, xdsfake.FakeOptions{})

	// Create a proxy in production namespace
	ads := s.ConnectADS().WithID("sidecar~10.0.0.1~test.production~production.svc.cluster.local")
	ads.RequestResponseAck(t, &discovery.DiscoveryRequest{TypeUrl: v3.ClusterType})

	tests := []struct {
		name       string
		callerNS   string
		proxyID    string
		wantStatus int
	}{
		{
			name:       "system namespace accesses any proxy",
			callerNS:   "istio-system",
			proxyID:    "test.production",
			wantStatus: 200,
		},
		{
			name:       "same namespace allowed",
			callerNS:   "production",
			proxyID:    "test.production",
			wantStatus: 200,
		},
		{
			name:       "cross-namespace denied",
			callerNS:   "staging",
			proxyID:    "test.production",
			wantStatus: 404, // Returns 404 when proxy not accessible
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			req, _ := http.NewRequest(http.MethodGet, "/debug/config_dump?proxyID="+tt.proxyID, nil)

			// Inject caller namespace into context (simulating auth middleware)
			ctx := context.WithValue(req.Context(), xds.CallerNamespaceKey{}, tt.callerNS)
			req = req.WithContext(ctx)

			rr := httptest.NewRecorder()
			handler := http.HandlerFunc(s.Discovery.ConfigDump)
			handler.ServeHTTP(rr, req)

			assert.Equal(t, rr.Code, tt.wantStatus,
				"namespace=%s accessing proxyID=%s", tt.callerNS, tt.proxyID)
		})
	}
}
Repository: istio/istio
File: tests/integration/security/pqc/main_test.go (Go)

Code before:
				t.ConfigIstio().Eval(i.Settings().SystemNamespace, egressConfig, drTmpl).ApplyOrFail(t, apply.Wait)

				a.CallOrFail(t, echo.CallOptions{
					To: server,
					Port: echo.Port{
						Protocol: protocol.HTTP,
					},
					Check: check.And(
						check.OK(),
						check.Each(func(r echoClient.Response) error {
							if _, f := r.RequestHeaders["Handled-By-Egress-Gateway"]; !f {
								return fmt.Errorf("expected request to be handled by egress gateway, response: %s", r)
							}
							return nil
						})),
				})
			})
		})
}

func checkTLSHandshakeFailure(t framework.TestContext) func(echo.CallResult, error) error {
	return func(_ echo.CallResult, err error) error {
		if err == nil {
			t.Error("expected to get TLS handshake error but got none")
		}
		if !strings.Contains(err.Error(), "tls: handshake failure") {
			t.Errorf("expected to get TLS handshake error but got: %s", err)
		}
		return nil
	}
}


Review comment (bug):
Please correct me if I am wrong here - I don't think `t.Error` stopes execution so if the error is nil this will result in a nil pointer dereference.

Code after:
				t.ConfigIstio().Eval(i.Settings().SystemNamespace, egressConfig, drTmpl).ApplyOrFail(t, apply.Wait)

				a.CallOrFail(t, echo.CallOptions{
					To: server,
					Port: echo.Port{
						Protocol: protocol.HTTP,
					},
					Check: check.And(
						check.OK(),
						check.Each(func(r echoClient.Response) error {
							if _, f := r.RequestHeaders["Handled-By-Egress-Gateway"]; !f {
								return fmt.Errorf("expected request to be handled by egress gateway, response: %s", r)
							}
							return nil
						})),
				})
			})
		})
}

func checkTLSHandshakeFailure(_ echo.CallResult, err error) error {
	if err == nil {
		return fmt.Errorf("expected to get TLS handshake error but got none")
	}
	if !strings.Contains(err.Error(), "tls: handshake failure") {
		return fmt.Errorf("expected to get TLS handshake error but got: %s", err)
	}
	return nil
}
Repository: istio/istio
File: pkg/kube/multicluster/component.go (Go)

Code before:

import (
	"sync"

	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/client-go/tools/cache"

	k8scluster "istio.io/istio/pkg/cluster"
	"istio.io/istio/pkg/kube/controllers"
	"istio.io/istio/pkg/kube/kclient"
	"istio.io/istio/pkg/kube/krt"
	"istio.io/istio/pkg/kube/kubetypes"
	"istio.io/istio/pkg/maps"
	"istio.io/istio/pkg/slices"
	"istio.io/istio/pkg/util/sets"
)

type ComponentConstraint interface {
	Close()
	HasSynced() bool
}

// pendingSwap wraps a new component during an update operation.
// It tracks both the old and new components, completing the swap only after the new one syncs.
type pendingSwap[T ComponentConstraint] struct {
	mu        sync.Mutex
	parent    *Component[T]
	clusterID k8scluster.ID
	old       T
	new       T
	hasOld    bool
}

func (p *pendingSwap[T]) Close() {
	p.new.Close()
}

func (p *pendingSwap[T]) HasSynced() bool {
	if !p.new.HasSynced() {
		return false
	}
	// New component is synced, finalize the swap by closing the old one
	p.mu.Lock()
	if p.hasOld {
		p.old.Close()
		p.hasOld = false
	}
	p.mu.Unlock()
	// Clear the pending swap from the parent's map since swap is complete
	if p.parent != nil {
		p.parent.mu.Lock()

Review comment (suggestion):
Seems like the mutex only protects a subset of fields? That is, `p.parent` doesn't require the lock? Would be good to document which fields are covered by the mutex or even embed a type for clarity.

Code after:

import (
	"sync"

	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/client-go/tools/cache"

	k8scluster "istio.io/istio/pkg/cluster"
	"istio.io/istio/pkg/kube/controllers"
	"istio.io/istio/pkg/kube/kclient"
	"istio.io/istio/pkg/kube/krt"
	"istio.io/istio/pkg/kube/kubetypes"
	"istio.io/istio/pkg/maps"
	"istio.io/istio/pkg/slices"
	"istio.io/istio/pkg/util/sets"
)

type ComponentConstraint interface {
	Close()
	HasSynced() bool
}

// pendingSwap wraps a new component during an update operation.
// It tracks both the old and new components, completing the swap only after the new one syncs.
//
// Thread safety: parent, clusterID, and new are immutable after construction.
// mu protects old and hasOld which can be modified by HasSynced().
type pendingSwap[T ComponentConstraint] struct {
	// mu protects old and hasOld fields only.
	mu sync.Mutex
	// Immutable after construction - no mutex needed.
	parent    *Component[T]
	clusterID k8scluster.ID
	new       T
	// Mutable fields protected by mu.
	old    T
	hasOld bool
}

func (p *pendingSwap[T]) Close() {
	p.new.Close()
}

func (p *pendingSwap[T]) HasSynced() bool {
	if !p.new.HasSynced() {
		return false
	}
	// New component is synced, finalize the swap by closing the old one
	p.mu.Lock()
	if p.hasOld {
		p.old.Close()
Repository: jaytaph/gosub-browser
File: src/html5_parser/node.rs (Rust)

Code before:

    #[test]
    fn test_type_of_node_data_comment() {
        let node = Node::new_comment("test");
        assert_eq!(
            node.data,
            NodeData::Comment {
                value: "test".to_string(),
            }
        );
    }

    #[test]
    fn test_type_of_node_data_document() {
        let node = Node::new_document();
        assert_eq!(node.data, NodeData::Document {});
    }

    #[test]
    fn test_contains_attribute_non_element() {
        let node = Node::new_document();
        let result = node.contains_attribute("x".to_string());
        match result {
            Err(_) => assert!(true),
            Ok(_) => assert!(false),
        }
    }

    #[test]
    fn test_contains_attribute() {
        let mut attr = HashMap::new();
        attr.insert("x".to_string(), "value".to_string());

        let node = Node::new_element("node", attr.clone(), HTML_NAMESPACE);

        match node.contains_attribute("x".to_string()) {
            Err(_) => assert!(false),
            Ok(result) => {
                assert_eq!(result, true);
            }
        }

        match node.contains_attribute("z".to_string()) {
            Err(_) => assert!(false),
            Ok(result) => {
                assert_eq!(result, false);
            }
        }
    }

    #[test]

Review comment (suggestion):
```suggestion
        assert!(result.is_err())
```


Code after:

    #[test]
    fn test_type_of_node_data_comment() {
        let node = Node::new_comment("test");
        assert_eq!(
            node.data,
            NodeData::Comment {
                value: "test".to_string(),
            }
        );
    }

    #[test]
    fn test_type_of_node_data_document() {
        let node = Node::new_document();
        assert_eq!(node.data, NodeData::Document {});
    }

    #[test]
    fn test_contains_attribute_non_element() {
        let node = Node::new_document();
        let result = node.contains_attribute("x".to_string());
        assert!(result.is_err())
    }

    #[test]
    fn test_contains_attribute() {
        let mut attr = HashMap::new();
        attr.insert("x".to_string(), "value".to_string());

        let node = Node::new_element("node", attr.clone(), HTML_NAMESPACE);

        match node.contains_attribute("x".to_string()) {
            Err(_) => assert!(false),
            Ok(result) => {
                assert_eq!(result, true);
            }
        }

        match node.contains_attribute("z".to_string()) {
            Err(_) => assert!(false),
            Ok(result) => {
                assert_eq!(result, false);
            }
        }
    }

    #[test]
    fn test_insert_attrubte_non_element() {
        let mut node = Node::new_document();
        let result = node.insert_attribute("name".to_string(), "value".to_string());
Repository: jaytaph/gosub-browser
File: src/api/console.rs (Rust)

Code before:
mod buffer;
mod formatter;
mod writable_printer;

use crate::api::console::formatter::Formatter;
use std::collections::HashMap;
use std::fmt;
use std::time::{SystemTime, UNIX_EPOCH};
use uuid::Uuid;

/// LogLevel is the type of log level.
#[derive(Debug)]
pub enum LogLevel {
    Info,
    Warn,
    Error,
    Log,
    Debug,
    Assert,
    Group,
    GroupCollapsed,
    GroupEnd,
    TimeLog,
    TimeEnd,
    Count,
    CountReset,

Review comment (suggestion):
```suggestion
//! The console API, as described by <https://console.spec.whatwg.org/>
```


Code after:
//! This module contains the console api as described by <https://console.spec.whatwg.org/>
mod buffer;
mod formatter;
mod writable_printer;

use crate::api::console::formatter::Formatter;
use std::collections::HashMap;
use std::fmt;
use std::time::{SystemTime, UNIX_EPOCH};
use uuid::Uuid;

/// LogLevel is the type of log level.
#[derive(Debug)]
pub enum LogLevel {
    Info,
    Warn,
    Error,
    Log,
    Debug,
    Assert,
    Group,
    GroupCollapsed,
    GroupEnd,
    TimeLog,
    TimeEnd,
    Count,
Repository: jaytaph/gosub-browser
File: src/html5_parser/input_stream.rs (Rust)

Code before:
impl fmt::Display for Position {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}:{}:{}", self.offset, self.line, self.col)
    }
}

#[derive(PartialEq, Debug, Copy, Clone)]
pub enum Element {
    /// Standard UTF character
    Utf8(char),
    /// Surrogate character (since they cannot be stored in <char>)
    Surrogate(u16),
    /// End of stream
    Eof,
}

impl Element {
    pub fn is_eof(&self) -> bool {
        matches!(self, Element::Eof)
    }

    pub fn is_utf8(&self) -> bool {
        matches!(self, Element::Utf8(_))
    }

    pub fn is_surrogate(&self) -> bool {
        matches!(self, Element::Surrogate(_))
    }

    pub fn u32(&self) -> u32 {
        match self {
            Element::Utf8(c) => *c as u32,
            Element::Surrogate(c) => *c as u32,
            Element::Eof => 0,
        }
    }

    pub fn utf8(&self) -> char {
        match self {
            Element::Utf8(c) => *c,
            Element::Surrogate(..) => 0x0000 as char,
            Element::Eof => 0x0000 as char,
        }
    }
}

impl fmt::Display for Element {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Element::Utf8(ch) => write!(f, "{}", ch),
            Element::Surrogate(surrogate) => write!(f, "U+{:04X}", surrogate),

Review comment (suggestion):
```suggestion
    /// Whether the element is an EOF
```

You get the idea.  Similar suggestions apply further down.

Code after:
    pub fn new(offset: usize, line: usize, col: usize) -> Self {
        Position { offset, line, col }
    }
}

impl fmt::Display for Position {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}:{}:{}", self.offset, self.line, self.col)
    }
}

/// Defines a single character/element in the stream. This is either a UTF8 character, or
/// a surrogate characters since these cannot be stored in a single char.
/// Eof is denoted as a separate element.
#[derive(PartialEq, Debug, Copy, Clone)]
pub enum Element {
    /// Standard UTF character
    Utf8(char),
    /// Surrogate character (since they cannot be stored in char)
    Surrogate(u16),
    /// End of stream
    Eof,
}

impl Element {
    /// Returns true when the element is an EOF
    pub fn is_eof(&self) -> bool {
        matches!(self, Element::Eof)
    }

    /// Returns true when the element is a UTF8 character
    pub fn is_utf8(&self) -> bool {
        matches!(self, Element::Utf8(_))
    }

    /// Returns true when the element is a surrogate character
    pub fn is_surrogate(&self) -> bool {
        matches!(self, Element::Surrogate(_))
    }

    /// Converts the given character to a u32
    pub fn u32(&self) -> u32 {
        match self {
            Element::Utf8(c) => *c as u32,
            Element::Surrogate(c) => *c as u32,
            Element::Eof => 0,
        }
    }

    /// Converts the given character to a char. This is only valid for UTF8 characters. Surrogate
    /// and EOF characters are converted to 0x0000