<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def sam_iter(handle, start_line=None, headers=False):
 """Iterate over SAM file and return SAM entries Args: handle (file):
 SAM file handle, can be any iterator so long as it it returns subsequent "lines" of a SAM entry start_line (str):
 Next SAM entry, if 'handle' has been partially read and you want to start iterating at the next entry, read the next SAM entry and pass it to this variable when calling sam_iter. See 'Examples.' headers (bool):
 Yields headers if True, else skips lines starting with "@" Yields: SamEntry: class containing all SAM data, yields str for headers if headers options is True then yields GamEntry for entries Examples: The following two examples demonstrate how to use sam_iter. Note: These doctests will not pass, examples are only in doctest format as per convention. bio_utils uses pytests for testing. """


    # Speed tricks: reduces function calls
    split = str.split
    strip = str.strip

    next_line = next

    if start_line is None:
        line = next_line(handle)  # Read first B6/M8 entry
    else:
        line = start_line  # Set header to given header

    # Check if input is text or bytestream
    if (isinstance(line, bytes)):
        def next_line(i):
            return next(i).decode('utf-8')

        line = strip(line.decode('utf-8'))
    else:
        line = strip(line)


    # A manual 'for' loop isn't needed to read the file properly and quickly,
    # unlike fasta_iter and fastq_iter, but it is necessary begin iterating
    # partway through a file when the user gives a starting line.
    try:  # Manually construct a for loop to improve speed by using 'next'

        while True:  # Loop until StopIteration Exception raised

            split_line = split(line, '\t')

            if line.startswith('@') and not headers:
                line = strip(next_line(handle))
                continue
            elif line.startswith('@') and headers:
                yield line
                line = strip(next_line(handle))
                continue

            data = SamEntry()
            data.qname = split_line[0]
            try:  # Differentiate between int and hex bit flags
                data.flag = int(split_line[1])
            except ValueError:
                data.flag = split_line[1]
            data.rname = split_line[2]
            data.pos = int(split_line[3])
            data.mapq = int(split_line[4])
            data.cigar = split_line[5]
            data.rnext = split_line[6]
            data.pnext = int(split_line[7])
            data.tlen = int(split_line[8])
            data.seq = split_line[9]
            data.qual = split_line[10]

            line = strip(next_line(handle))  # Raises StopIteration at EOF

            yield data

    except StopIteration:  # Yield last SAM entry
        yield data