@@ -12,7 +12,6 @@ import (
1212"internal/nettrace"
1313"net"
1414"net/textproto"
15- "reflect"
1615"time"
1716)
1817
@@ -176,34 +175,86 @@ func (t *ClientTrace) compose(old *ClientTrace) {
176175if old == nil {
177176return
178177}
179- tv := reflect . ValueOf ( t ). Elem ( )
180- ov := reflect . ValueOf ( old ). Elem ( )
181- structType := tv . Type ( )
182- for i := 0 ; i < structType . NumField (); i ++ {
183- tf := tv . Field ( i )
184- hookType := tf . Type ( )
185- if hookType . Kind () != reflect . Func {
186- continue
187- }
188- of := ov . Field ( i )
189- if of . IsNil () {
190- continue
191- }
192- if tf . IsNil () {
193- tf . Set ( of )
194- continue
195- }
178+ t . GetConn = compose1to0 ( t . GetConn , old . GetConn )
179+ t . GotConn = compose1to0 ( t . GotConn , old . GotConn )
180+ t . PutIdleConn = compose1to0 ( t . PutIdleConn , old . PutIdleConn )
181+ t . GotFirstResponseByte = compose0to0 ( t . GotFirstResponseByte , old . GotFirstResponseByte )
182+ t . Got100Continue = compose0to0 ( t . Got100Continue , old . Got100Continue )
183+ t . Got1xxResponse = compose2to1 ( t . Got1xxResponse , old . Got1xxResponse )
184+ t . DNSStart = compose1to0 ( t . DNSStart , old . DNSStart )
185+ t . DNSDone = compose1to0 ( t . DNSDone , old . DNSDone )
186+ t . ConnectStart = compose2to0 ( t . ConnectStart , old . ConnectStart )
187+ t . ConnectDone = compose3to0 ( t . ConnectDone , old . ConnectDone )
188+ t . TLSHandshakeStart = compose0to0 ( t . TLSHandshakeStart , old . TLSHandshakeStart )
189+ t . TLSHandshakeDone = compose2to0 ( t . TLSHandshakeDone , old . TLSHandshakeDone )
190+ t . WroteHeaderField = compose2to0 ( t . WroteHeaderField , old . WroteHeaderField )
191+ t . WroteHeaders = compose0to0 ( t . WroteHeaders , old . WroteHeaders )
192+ t . Wait100Continue = compose0to0 ( t . Wait100Continue , old . Wait100Continue )
193+ t . WroteRequest = compose1to0 ( t . WroteRequest , old . WroteRequest )
194+ }
196195
197- // Make a copy of tf for tf to call. (Otherwise it
198- // creates a recursive call cycle and stack overflows)
199- tfCopy := reflect .ValueOf (tf .Interface ())
196+ func compose0to0 [F func ()](f1 , f2 F ) F {
197+ if f1 == nil {
198+ return f2
199+ }
200+ if f2 == nil {
201+ return f1
202+ }
203+ return func () {
204+ f1 ()
205+ f2 ()
206+ }
207+ }
208+
209+ func compose1to0 [F func (A ), A any ](f1 , f2 F ) F {
210+ if f1 == nil {
211+ return f2
212+ }
213+ if f2 == nil {
214+ return f1
215+ }
216+ return func (a A ) {
217+ f1 (a )
218+ f2 (a )
219+ }
220+ }
200221
201- // We need to call both tf and of in some order.
202- newFunc := reflect .MakeFunc (hookType , func (args []reflect.Value ) []reflect.Value {
203- tfCopy .Call (args )
204- return of .Call (args )
205- })
206- tv .Field (i ).Set (newFunc )
222+ func compose2to0 [F func (A , B ), A , B any ](f1 , f2 F ) F {
223+ if f1 == nil {
224+ return f2
225+ }
226+ if f2 == nil {
227+ return f1
228+ }
229+ return func (a A , b B ) {
230+ f1 (a , b )
231+ f2 (a , b )
232+ }
233+ }
234+
235+ func compose2to1 [F func (A , B ) R , A , B , R any ](f1 , f2 F ) F {
236+ if f1 == nil {
237+ return f2
238+ }
239+ if f2 == nil {
240+ return f1
241+ }
242+ return func (a A , b B ) R {
243+ f1 (a , b )
244+ return f2 (a , b )
245+ }
246+ }
247+
248+ func compose3to0 [F func (A , B , C ), A , B , C any ](f1 , f2 F ) F {
249+ if f1 == nil {
250+ return f2
251+ }
252+ if f2 == nil {
253+ return f1
254+ }
255+ return func (a A , b B , c C ) {
256+ f1 (a , b , c )
257+ f2 (a , b , c )
207258}
208259}
209260
0 commit comments