blob: ff5ef01a665d17c80756f822718091deb38d2a74 [file]
// Copyright 2026 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package http3
import (
"fmt"
"net/http"
"reflect"
_ "unsafe" // for linkname
. "golang.org/x/net/internal/http3"
)
//go:linkname registerServer net/http_test.registerHTTP3Server
func registerServer(s *http.Server, opts any) error {
var o ServerOpts
if err := shallowStructCopy(&o, opts); err != nil {
return err
}
return RegisterServer(s, o)
}
//go:linkname registerTransport net/http_test.registerHTTP3Transport
func registerTransport(tr *http.Transport, opts any) error {
var o TransportOpts
if err := shallowStructCopy(&o, opts); err != nil {
return err
}
return RegisterTransport(tr, o)
}
// shallowStructCopy copies every field in src to *dst.
// src must be a struct, and dst must be a pointer to a struct.
//
// We use this to let net/http tests pass their own version of an options struct to
// registerHTTP3{Server,Transport}.
//
// This is a temporary measure pending this package having a public API,
// at which time net/http tests can use the ServerOpts and TransportOpts directly.
func shallowStructCopy(dst, src any) error {
dv := reflect.ValueOf(dst).Elem()
sv := reflect.ValueOf(src)
for i := range sv.Type().NumField() {
stype := sv.Type().Field(i)
if !stype.IsExported() {
return fmt.Errorf("%T contains unexported fields", src)
}
sf := sv.Field(i)
df := dv.FieldByName(stype.Name)
if !df.CanSet() {
return fmt.Errorf("%T.%v: field does not exist or is unassignable", dst, stype.Name)
}
if !sf.Type().AssignableTo(df.Type()) {
return fmt.Errorf("%T.%v: %v is not assignable to %v", dst, stype.Name, sf.Type(), df.Type())
}
df.Set(sf)
}
return nil
}