func (od *OfflineDatabase) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	switch {
	case strings.HasPrefix(r.URL.Path, "/pwnedpassword/"):
		pw := bytes.TrimPrefix([]byte(r.URL.Path), []byte("/pwnedpassword/"))
		var hash [20]byte
		if hh, ok := isHash(pw); ok {
			hash = hh
		} else {
			hash = sha1.Sum([]byte(pw))
		}
		frequency, err := od.Pwned(hash)
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			return
		}
		if frequency == 0 {
			w.WriteHeader(http.StatusNotFound)
			fmt.Fprintln(w, "Password not compromised")
		} else {
			w.WriteHeader(http.StatusOK)
			fmt.Fprintln(w, frequency)
		}
	case strings.HasPrefix(r.URL.Path, "/range/"):
		prefix := bytes.TrimPrefix([]byte(r.URL.Path), []byte("/range/"))
		if !isHashPrefix(prefix) {
			w.WriteHeader(http.StatusBadRequest)
			w.Write([]byte("The hash prefix was not in a valid format"))
			return
		}
		var hash [20]byte       
		var hexhash [40]byte    
		var buffer [64]byte     
		var start, end [3]byte  
		hex.Decode(start[:], append(prefix, byte('0')))
		hex.Decode(end[:], append(prefix, byte('F')))
		response := bytes.NewBuffer(buffer[:])
		od.Scan(start, end, hash[:], func(freq uint16) bool {
			for i, v := range hash[:] {
				hexhash[i*2] = caphextable[v>>4]
				hexhash[i*2+1] = caphextable[v&0x0f]
			}
			response.Truncate(0)
			response.Write(hexhash[5:])
			response.Write([]byte{':'})
			response.WriteString(strconv.FormatInt(int64(freq), 10))
			response.Write([]byte{'\r', '\n'})
			w.Write(response.Bytes())
			return false
		})
	default:
		w.WriteHeader(http.StatusNotFound)
		return
	}
}
ServeHTTP implements the http.Handler interface by approximating the online
Pwned Password V2 API. The following routes are available:

/pwnedpassword/password
/pwnedpassword/hash
/range/ABCDE

Their behavior is very similar to that of the online equivalent; the same
documentation should apply.
package pwnedpass
import (
	"bytes"
	"crypto/sha1"
	"encoding/binary"
	"encoding/hex"
	"errors"
	"fmt"
	"io"
	"net/http"
	"strconv"
	"strings"
	"sync"
	"golang.org/x/exp/mmap"
)
const (
	DatabaseFilename = "pwned-passwords.bin"
	IndexSegmentSize = 256 << 16 << 3  
	DataSegmentOffset = IndexSegmentSize
	caphextable = "0123456789ABCDEF"
)
var (
	FirstPrefix = [3]byte{0x00, 0x00, 0x00}
	LastPrefix = [3]byte{0xFF, 0xFF, 0xFF}
	bufferPool = &sync.Pool{New: func() interface{} {
		return make([]byte, 8<<10)
	}}
)
type (
	OfflineDatabase struct {
		database readCloserAt
	}
	readCloserAt interface {
		io.ReaderAt
		io.Closer
		Len() int
	}
)
func NewOfflineDatabase(dbFile string) (*OfflineDatabase, error) {
	db, err := mmap.Open(dbFile)
	if err != nil {
		return nil, fmt.Errorf("error opening index: %s", err)
	}
	odb := &OfflineDatabase{
		database: db,
	}
	return odb, nil
}
func (od *OfflineDatabase) Close() error {
	return od.database.Close()
}
func (od *OfflineDatabase) Pwned(hash [20]byte) (frequency int, err error) {
	var prefix [3]byte
	copy(prefix[0:3], hash[0:3])
	var pwnedHash [20]byte
	err = od.Scan(prefix, prefix, pwnedHash[:], func(freq uint16) bool {
		if pwnedHash == hash {
			frequency = int(freq)
			return true
		}
		return false
	})
	return frequency, err
}
func (od *OfflineDatabase) Scan(startPrefix, endPrefix [3]byte, hash []byte, cb func(frequency uint16) bool) error {
	if bytes.Compare(startPrefix[:], endPrefix[:]) == 1 {
		return errors.New("invalid range: startPrefix > endPrefix")
	}
	buffer := bufferPool.Get().([]byte)
	var shortPrefix [3]byte = startPrefix
	var fullPrefix [4]byte
	copy(fullPrefix[1:4], startPrefix[0:3])
	copy(hash[0:3], startPrefix[0:3])
	var currentPrefix uint32 = binary.BigEndian.Uint32(fullPrefix[:])
	for {
		start, length, err := od.lookup(shortPrefix)
		if err != nil {
			return err
		}
		if _, err := od.database.ReadAt(buffer[0:length], DataSegmentOffset+start); err != nil {
			return err
		}
		for offset := int64(0); offset < length; offset += 19 {
			copy(hash[3:20], buffer[offset:offset+17])
			frequency := uint16(binary.BigEndian.Uint16(buffer[offset+17 : offset+19]))
			if stop := cb(frequency); stop {
				return nil
			}
		}
		if shortPrefix == endPrefix {
			break
		}
		currentPrefix++
		binary.BigEndian.PutUint32(fullPrefix[0:4], currentPrefix)
		copy(shortPrefix[0:3], fullPrefix[1:4])
		copy(hash[0:3], fullPrefix[1:4])
		if currentPrefix > 256<<16 {
			break
		}
	}
	return nil
}
func (od *OfflineDatabase) lookup(start [3]byte) (location, length int64, err error) {
	var buffer [16]byte
	copy(buffer[1:4], start[:])
	prefixIndex := binary.BigEndian.Uint32(buffer[0:4])  
	var loc, dataLen int64
	switch start {
	case [3]byte{0xFF, 0xFF, 0xFF}:
		if _, err := od.database.ReadAt(buffer[0:8], int64(prefixIndex)*8); err != nil {
			return 0, 0, err
		}
		loc = int64(binary.BigEndian.Uint64(buffer[0:8]))
		dataLen = int64(od.database.Len()-IndexSegmentSize) - loc
	default:
		if _, err := od.database.ReadAt(buffer[0:16], int64(prefixIndex)*8); err != nil {
			return 0, 0, err
		}
		var nextLoc int64
		loc, nextLoc = int64(binary.BigEndian.Uint64(buffer[0:8])), int64(binary.BigEndian.Uint64(buffer[8:16]))
		dataLen = nextLoc - loc
	}
	return loc, dataLen, nil
}