func DiffPrinters(nativePrinters, gcpPrinters []Printer) []PrinterDiff {
	dirty := false
	diffs := make([]PrinterDiff, 0, 1)
	printersConsidered := make(map[string]struct{}, len(nativePrinters))
	nativePrintersByName := printerSliceToMapByName(nativePrinters)
	for i := range gcpPrinters {
		if _, exists := printersConsidered[gcpPrinters[i].Name]; exists {
			diffs = append(diffs, PrinterDiff{Operation: DeletePrinter, Printer: gcpPrinters[i]})
			dirty = true
		} else {
			printersConsidered[gcpPrinters[i].Name] = struct{}{}
			if nativePrinter, exists := nativePrintersByName[gcpPrinters[i].Name]; exists {
				nativePrinter.GCPID = gcpPrinters[i].GCPID
				nativePrinter.NativeJobSemaphore = gcpPrinters[i].NativeJobSemaphore
				diff := diffPrinter(&nativePrinter, &gcpPrinters[i])
				diffs = append(diffs, diff)
				if diff.Operation != NoChangeToPrinter {
					dirty = true
				}
			} else {
				diffs = append(diffs, PrinterDiff{Operation: DeletePrinter, Printer: gcpPrinters[i]})
				dirty = true
			}
		}
	}
	for i := range nativePrinters {
		if _, exists := printersConsidered[nativePrinters[i].Name]; !exists {
			diffs = append(diffs, PrinterDiff{Operation: RegisterPrinter, Printer: nativePrinters[i]})
			dirty = true
		}
	}
	if dirty {
		return diffs
	} else {
		return nil
	}
}
DiffPrinters returns the diff between old (GCP) and new (native) printers.
Returns nil if zero printers or if all diffs are NoChangeToPrinter operation.
package lib
import (
	"reflect"
	"regexp"
	"github.com/google/cloud-print-connector/cdd"
)
type PrinterState uint8
type DuplexVendorMap map[cdd.DuplexType]string
type Printer struct {
	GCPID               string                          
	Name                string                          
	DefaultDisplayName  string                          
	UUID                string                          
	Manufacturer        string                          
	Model               string                          
	GCPVersion          string                          
	SetupURL            string                          
	SupportURL          string                          
	UpdateURL           string                          
	ConnectorVersion    string                          
	State               *cdd.PrinterStateSection        
	Description         *cdd.PrinterDescriptionSection  
	CapsHash            string                          
	Tags                map[string]string               
	DuplexMap           DuplexVendorMap                 
	NativeJobSemaphore  *Semaphore
	QuotaEnabled        bool
	DailyQuota          int
	NotificationChannel string
}
var rDeviceURIHostname *regexp.Regexp = regexp.MustCompile(
	"(?i)^(?:socket|http|https|ipp|ipps|lpd)://([a-z][a-z0-9.-]*)")
func (p *Printer) GetHostname() (string, bool) {
	deviceURI, ok := p.Tags["device-uri"]
	if !ok {
		return "", false
	}
	parts := rDeviceURIHostname.FindStringSubmatch(deviceURI)
	if len(parts) == 2 {
		return parts[1], true
	}
	return "", false
}
type PrinterDiffOperation int8
const (
	RegisterPrinter PrinterDiffOperation = iota
	UpdatePrinter
	DeletePrinter
	NoChangeToPrinter
)
type PrinterDiff struct {
	Operation PrinterDiffOperation
	Printer   Printer
	DefaultDisplayNameChanged  bool
	ManufacturerChanged        bool
	ModelChanged               bool
	GCPVersionChanged          bool
	SetupURLChanged            bool
	SupportURLChanged          bool
	UpdateURLChanged           bool
	ConnectorVersionChanged    bool
	StateChanged               bool
	DescriptionChanged         bool
	CapsHashChanged            bool
	TagsChanged                bool
	DuplexMapChanged           bool
	QuotaEnabledChanged        bool
	DailyQuotaChanged          bool
	NotificationChannelChanged bool
}
func printerSliceToMapByName(s []Printer) map[string]Printer {
	m := make(map[string]Printer, len(s))
	for i := range s {
		m[s[i].Name] = s[i]
	}
	return m
}